[med-svn] [beast2-mcmc] 01/04: Imported Upstream version 2.4.2+dfsg

Andreas Tille tille at debian.org
Mon Jul 18 12:15:27 UTC 2016


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

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

commit 4a468e49e06378c4fc77b5e695f1d30c034358cf
Author: Andreas Tille <tille at debian.org>
Date:   Mon Jul 18 13:55:31 2016 +0200

    Imported Upstream version 2.4.2+dfsg
---
 build.xml                                          |   2 +-
 release/common/README.txt                          |   4 +-
 release/common/VERSION HISTORY.txt                 |  17 +-
 src/beast/app/BEASTVersion.java                    |   4 +-
 src/beast/app/BEASTVersion2.java                   |   4 +-
 src/beast/app/BeastMCMC.java                       |   4 +-
 src/beast/app/ModelBuilder.java                    |   4 +-
 src/beast/app/beastapp/BeastDialog.java            |   4 +-
 src/beast/app/beastapp/BeastLauncher.java          |   2 +-
 src/beast/app/beastapp/BeastMain.java              |  78 +++++---
 src/beast/app/beauti/AlignmentListInputEditor.java |   4 +-
 src/beast/app/beauti/AlignmentViewer.java          |   6 +-
 src/beast/app/beauti/Beauti.java                   |  47 ++++-
 src/beast/app/beauti/BeautiDoc.java                |   3 +
 src/beast/app/beauti/BeautiSubTemplate.java        |   2 +-
 src/beast/app/beauti/JPackageDialog.java           |   3 +-
 src/beast/app/beauti/MRCAPriorInputEditor.java     |   4 +-
 .../beauti/ParametricDistributionInputEditor.java  |   8 +-
 src/beast/app/beauti/PriorInputEditor.java         |  15 +-
 src/beast/app/beauti/TaxonSetDialog.java           |   4 +-
 src/beast/app/beauti/TipDatesInputEditor.java      |   5 +-
 .../app/beauti/TreeDistributionInputEditor.java    |   8 +-
 src/beast/app/draw/BEASTObjectShape.java           |   3 +-
 src/beast/app/draw/HelpBrowser.java                |   4 +-
 src/beast/app/draw/InputEditor.java                |  15 +-
 src/beast/app/draw/IntegerListInputEditor.java     |   9 +-
 src/beast/app/draw/ModelBuilder.java               |   7 +-
 src/beast/app/tools/AppStore.java                  |   5 +-
 src/beast/app/tools/EBSPAnalyser.java              |   8 +-
 src/beast/app/tools/LogCombiner.java               | 218 +++++++++++++++------
 src/beast/app/tools/LogCombinerDialog.java         |   3 +-
 src/beast/app/treeannotator/TreeAnnotator.java     |  36 ++--
 src/beast/app/util/Utils.java                      |  99 +++++++++-
 src/beast/core/BEASTInterface.java                 |   6 +
 src/beast/core/BEASTObject.java                    |   5 +-
 src/beast/core/Logger.java                         |  57 +++---
 src/beast/core/MCMC.java                           |  18 +-
 .../evolution/speciation/CalibratedYuleModel.java  |  22 ++-
 .../evolution/speciation/SpeciesTreePrior.java     |   4 +-
 .../substitutionmodel/BinaryCovarion.java          |  23 ++-
 src/beast/evolution/tree/Node.java                 |   2 +-
 src/beast/evolution/tree/RandomTree.java           |  21 +-
 src/beast/evolution/tree/Tree.java                 |   3 +
 src/beast/util/AddOnManager.java                   |  62 ++----
 src/beast/util/FrequencySet.java                   |   3 +
 src/beast/util/NexusParser.java                    |   2 +-
 src/beast/util/XMLProducer.java                    |  24 ++-
 src/test/beast/app/tools/LogCombinerTest.java      | 197 +++++++++++++++++++
 src/test/beast/core/LoggerTest.java                | 129 ++++++++++++
 .../substmodel/BinaryCovarionModelTest.java        | 125 ++++++++++++
 templates/ClockModels.xml                          |   5 +-
 version.xml                                        |   2 +-
 52 files changed, 1076 insertions(+), 273 deletions(-)

diff --git a/build.xml b/build.xml
index ba0e4f1..3c6a376 100644
--- a/build.xml
+++ b/build.xml
@@ -242,7 +242,7 @@
 
 
     <!-- Release -->
-    <property name="version" value="2.4.1" />
+    <property name="version" value="2.4.2" />
     <property name="version_number" value="2.4.0" />
     <property name="release_dir" value="release" />
     <property name="copyright" value="Beast 2 development team 2011-2016" />
diff --git a/release/common/README.txt b/release/common/README.txt
index 44ca6a8..dae7c51 100644
--- a/release/common/README.txt
+++ b/release/common/README.txt
@@ -1,7 +1,7 @@
-                    BEAST v2.4.1 2016
+                    BEAST v2.4.2 2016
                  Beast 2 development team 2011-2016
 
-Last updated: April 2016
+Last updated: June 2016
 
 Contents:
 1) INTRODUCTION
diff --git a/release/common/VERSION HISTORY.txt b/release/common/VERSION HISTORY.txt
index 116e751..19b6d1e 100644
--- a/release/common/VERSION HISTORY.txt	
+++ b/release/common/VERSION HISTORY.txt	
@@ -1,10 +1,23 @@
-                    BEAST v2.4.1 2016
+                    BEAST v2.4.2 2016
                  Beast 2 development team 2011-2016
 Version History
-Last updated: March 2016
+Last updated: June 2016
 
 All issues can be viewed at https://github.com/CompEvol/beast2/issues
 ================================================================================
+Version 2.4.2 June 2016
+     Applications are scalable, making them visible on high resolution screens
+
+     BEAUti
+         improved error reporting
+     BEAST
+         improved error reporting
+         prevent closing window on parsing errors
+     
+     LogCombiner requires much less memory than before
+     
+     Densitree updated to version 2.2.5
+     
 Version 2.4.1 April 2016
      BEAUti
          import of calibrations from NEXUS files
diff --git a/src/beast/app/BEASTVersion.java b/src/beast/app/BEASTVersion.java
index 9674787..a8b8e03 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.4.1";
+    private static final String VERSION = "2.4.2";
 
     private static final String DATE_STRING = "2002-2016";
 
-    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/BEASTVersion2.java b/src/beast/app/BEASTVersion2.java
index c1c0a28..6e029ae 100644
--- a/src/beast/app/BEASTVersion2.java
+++ b/src/beast/app/BEASTVersion2.java
@@ -9,11 +9,11 @@ public class BEASTVersion2 extends BEASTVersion {
     /**
      * Version string: assumed to be in format x.x.x
      */
-    private static final String VERSION = "2.4.1";
+    private static final String VERSION = "2.4.2";
 
     private static final String DATE_STRING = "2002-2016";
 
-    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/BeastMCMC.java b/src/beast/app/BeastMCMC.java
index b091cc1..974b38a 100644
--- a/src/beast/app/BeastMCMC.java
+++ b/src/beast/app/BeastMCMC.java
@@ -50,6 +50,7 @@ import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
+import javax.swing.UIManager;
 import javax.swing.WindowConstants;
 import javax.swing.border.EtchedBorder;
 import javax.swing.filechooser.FileFilter;
@@ -378,7 +379,8 @@ public class BeastMCMC {
                 box.add(Box.createVerticalGlue());
                 box.add(createRunQuitButtons());
                 add(box);
-                setSize(new Dimension(600, 500));
+                int size = UIManager.getFont("Label.font").getSize();
+                setSize(600 * size / 13, 500 * size / 13);
             } catch (Exception e) {
                 e.printStackTrace();
                 JOptionPane.showMessageDialog(this, "Could not create dialog: " + e.getMessage());
diff --git a/src/beast/app/ModelBuilder.java b/src/beast/app/ModelBuilder.java
index 5d0c94a..5035be8 100644
--- a/src/beast/app/ModelBuilder.java
+++ b/src/beast/app/ModelBuilder.java
@@ -33,6 +33,7 @@ import javax.swing.ImageIcon;
 import javax.swing.JFrame;
 import javax.swing.JMenuBar;
 import javax.swing.JPanel;
+import javax.swing.UIManager;
 
 import beast.util.AddOnManager;
 import beast.util.Randomizer;
@@ -83,7 +84,8 @@ public class ModelBuilder extends JPanel {
             drawTest.m_doc.loadFile(args[0]);
             drawTest.setDrawingFlag();
         }
-        f.setSize(600, 800);
+        int size = UIManager.getFont("Label.font").getSize();
+        f.setSize(600 * size / 13, 800 * size / 13);
         f.setVisible(true);
     } // main
 }
diff --git a/src/beast/app/beastapp/BeastDialog.java b/src/beast/app/beastapp/BeastDialog.java
index d129c62..a56159b 100644
--- a/src/beast/app/beastapp/BeastDialog.java
+++ b/src/beast/app/beastapp/BeastDialog.java
@@ -16,6 +16,7 @@ import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.UIManager;
 import javax.swing.border.EmptyBorder;
 import javax.swing.border.TitledBorder;
 import javax.swing.event.ChangeEvent;
@@ -59,7 +60,8 @@ public class BeastDialog {
         final JLabel titleText = new JLabel(titleString);
         titleText.setIcon(icon);
         optionPanel.addSpanningComponent(titleText);
-        titleText.setFont(new Font("sans-serif", 0, 12));
+        Font font = UIManager.getFont("Label.font");
+        titleText.setFont(new Font("sans-serif", font.getStyle(), font.getSize()));
 
         final JButton inputFileButton = new JButton("Choose File...");
         final JTextField inputFileNameText = new JTextField("not selected", 16);
diff --git a/src/beast/app/beastapp/BeastLauncher.java b/src/beast/app/beastapp/BeastLauncher.java
index 128d90f..198c1f8 100644
--- a/src/beast/app/beastapp/BeastLauncher.java
+++ b/src/beast/app/beastapp/BeastLauncher.java
@@ -29,7 +29,7 @@ import beast.app.util.Utils6;
  * remainder of BEAST can be compiled against Java 1.8
  * **/
 public class BeastLauncher {
-	private static String getVersion() {return "2.4.1";}
+	private static String getVersion() {return "2.4.2";}
 	private static String getMajorVersion() {return "2.4";}
 	
 	private static String pathDelimiter;
diff --git a/src/beast/app/beastapp/BeastMain.java b/src/beast/app/beastapp/BeastMain.java
index a92ee3b..20f4c58 100644
--- a/src/beast/app/beastapp/BeastMain.java
+++ b/src/beast/app/beastapp/BeastMain.java
@@ -59,6 +59,13 @@ public class BeastMain {
     }
 
     public BeastMain(final BeastMCMC beastMCMC, final BeastConsoleApp consoleApp, final int maxErrorCount) {
+        // make sure Log output ends up in the console
+		Log.err = System.err;
+		Log.warning = System.err;
+		Log.info = System.out;
+		Log.debug = System.out;
+		Log.trace = System.out;
+
 
         final Logger infoLogger = Logger.getLogger("beast.app");
         try {
@@ -161,10 +168,10 @@ public class BeastMain {
             }
             */
         } catch (XMLParserException e) {
-           System.out.println(e.getMessage());
+           Log.info.println(e.getMessage());
             //e.printStackTrace();
         } catch (Exception e) {
-            System.out.println("Fatal exception: " + e.getMessage());
+            Log.info.println("Fatal exception: " + e.getMessage());
             e.printStackTrace(System.err);
             infoLogger.severe("Fatal exception: " + e.getMessage());
         }
@@ -206,32 +213,32 @@ public class BeastMain {
         final int n = pageWidth - line.length();
         final int n1 = n / 2;
         for (int i = 0; i < n1; i++) {
-            System.out.print(" ");
+            Log.info.print(" ");
         }
-        System.out.println(line);
+        Log.info.println(line);
     }
 
     public static void printTitle() {
 
         int pageWidth = 72;
 
-        System.out.println();
+        Log.info.println();
         centreLine("BEAST " + version.getVersionString() + ", " + version.getDateString(), pageWidth);
         centreLine("Bayesian Evolutionary Analysis Sampling Trees", pageWidth);
         for (final String creditLine : version.getCredits()) {
             centreLine(creditLine, pageWidth);
         }
-        System.out.println();
+        Log.info.println();
     }
 
     public static void printUsage(final Arguments arguments) {
 
         arguments.printUsage("beast", "[<input-file-name>]");
-        System.out.println();
-        System.out.println("  Example: beast test.xml");
-        System.out.println("  Example: beast -window test.xml");
-        System.out.println("  Example: beast -help");
-        System.out.println();
+        Log.info.println();
+        Log.info.println("  Example: beast test.xml");
+        Log.info.println("  Example: beast -window test.xml");
+        Log.info.println("  Example: beast -help");
+        Log.info.println();
     }
 
     //Main method
@@ -279,15 +286,15 @@ public class BeastMain {
         try {
             arguments.parseArguments(args);
         } catch (Arguments.ArgumentException ae) {
-        	System.out.println();
-        	System.out.println(ae.getMessage());
-        	System.out.println();
+        	Log.info.println();
+        	Log.info.println(ae.getMessage());
+        	Log.info.println();
             printUsage(arguments);
             System.exit(1);
         }
 
         if (arguments.hasOption("version")) {
-        	System.out.println((new BEASTVersion2()).getVersionString());
+        	Log.info.println((new BEASTVersion2()).getVersionString());
         	System.exit(0);
         }
 
@@ -389,14 +396,14 @@ public class BeastMain {
         }
         if (threadCount <= 0) {
         	threadCount = Runtime.getRuntime().availableProcessors();
-        	System.err.println("Setting number of threads to " + threadCount);
+        	Log.warning.println("Setting number of threads to " + threadCount);
         }
 
         if (arguments.hasOption("seed")) {
             seed = arguments.getLongOption("seed");
             if (seed <= 0) {
                 printTitle();
-                System.err.println("The random number seed should be > 0");
+                Log.err.println("The random number seed should be > 0");
                 System.exit(1);
             }
         }
@@ -429,6 +436,12 @@ public class BeastMain {
                     "</div></center></div></html>";
 
             consoleApp = new BeastConsoleApp(nameString, aboutString, icon);
+            
+            // ensure error and info information is shown in console
+            // but not warning, debug or trace, since that typically just
+            // results in a lot of clutter
+            Log.err = System.err;
+    		Log.info = System.out;
         }
 
         printTitle();
@@ -436,7 +449,8 @@ public class BeastMain {
         File inputFile = null;
 
         if (options) {
-
+        	Utils.loadUIManager();
+        	
             final String titleString = "<html><center><p>Bayesian Evolutionary Analysis Sampling Trees<br>" +
                     "Version " + version.getVersionString() + ", " + version.getDateString() + "</p></center></html>";
             final javax.swing.Icon icon = IconUtils.getIcon(BeastMain.class, "images/beast.png");
@@ -486,7 +500,7 @@ public class BeastMain {
 
             inputFile = dialog.getInputFile();
             if (!beagleShowInfo && inputFile == null) {
-            	System.err.println("No input file specified");
+            	Log.err.println("No input file specified");
                 System.exit(1);
             }
 
@@ -510,8 +524,8 @@ public class BeastMain {
             final String[] args2 = arguments.getLeftoverArguments();
 
             if (args2.length > 1) {
-            	System.err.println("Unknown option: " + args2[1]);
-            	System.err.println();
+            	Log.err.println("Unknown option: " + args2[1]);
+            	Log.err.println();
                 printUsage(arguments);
                 System.exit(1);
             }
@@ -577,7 +591,7 @@ public class BeastMain {
 
         if (stateFileName!= null && stateFileName.trim().length() > 0) {
             System.setProperty("state.file.name", stateFileName.trim());
-            System.out.println("Writing state to file " + stateFileName);
+            Log.info.println("Writing state to file " + stateFileName);
         }
 
 //        if (allowOverwrite) {
@@ -599,8 +613,8 @@ public class BeastMain {
         MCMCargs.add(seed + "");
         Randomizer.setSeed(seed);
 
-        System.out.println("Random number seed: " + seed);
-        System.out.println();
+        Log.info.println("Random number seed: " + seed);
+        Log.info.println();
 
         // Construct the beast object
         final BeastMCMC beastMCMC = new BeastMCMC();
@@ -613,7 +627,7 @@ public class BeastMain {
             if (!doNotRun) {
             	new BeastMain(beastMCMC, consoleApp, maxErrorCount);
             } else {
-            	System.out.println("Done!");
+            	Log.info.println("Done!");
             }
         } catch (RuntimeException rte) {
             if (window) {
@@ -624,16 +638,20 @@ public class BeastMain {
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
-                System.out.println();
-                System.out.println("BEAST has terminated with an error. Please select QUIT from the menu.");
+                Log.info.println();
+                Log.info.println("BEAST has terminated with an error. Please select QUIT from the menu.");
             }
             // logger.severe will throw a RTE but we want to keep the console visible
         } catch (XMLParserException e) {
-            System.out.println(e.getMessage());
-            System.exit(1);
+            Log.info.println(e.getMessage());
+            if (!window) {
+            	System.exit(1);
+            }
         } catch (Exception e) {
             e.printStackTrace();
-            System.exit(1);
+            if (!window) {
+            	System.exit(1);
+            }
         }
 
         if (!window) {
diff --git a/src/beast/app/beauti/AlignmentListInputEditor.java b/src/beast/app/beauti/AlignmentListInputEditor.java
index 41997cc..c6d7f65 100644
--- a/src/beast/app/beauti/AlignmentListInputEditor.java
+++ b/src/beast/app/beauti/AlignmentListInputEditor.java
@@ -486,6 +486,7 @@ public class AlignmentListInputEditor extends ListInputEditor {
 
 			}
 			if (tree != null && tree != this.likelihoods[rowNr].treeInput.get()) {
+				JOptionPane.showMessageDialog(this, "Cannot link clock model with different trees");
 				throw new IllegalArgumentException("Cannot link clock model with different trees");
 			}
 
@@ -740,7 +741,8 @@ public class AlignmentListInputEditor extends ListInputEditor {
 				return comp;
 			}
 		};
-		table.setRowHeight(25);
+		int size = table.getFont().getSize();
+		table.setRowHeight(25 * size/13);
 		table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 		table.setColumnSelectionAllowed(false);
 		table.setRowSelectionAllowed(true);
diff --git a/src/beast/app/beauti/AlignmentViewer.java b/src/beast/app/beauti/AlignmentViewer.java
index eaf25ed..8ab6b75 100644
--- a/src/beast/app/beauti/AlignmentViewer.java
+++ b/src/beast/app/beauti/AlignmentViewer.java
@@ -17,6 +17,7 @@ import javax.swing.JTable;
 import javax.swing.JViewport;
 import javax.swing.ListSelectionModel;
 import javax.swing.ScrollPaneConstants;
+import javax.swing.UIManager;
 import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableColumn;
 import javax.swing.table.TableModel;
@@ -130,7 +131,7 @@ public class AlignmentViewer extends JPanel {
         JTable fixedTable = new JTable(fixedColumnModel);
         fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
         Font font = fixedTable.getFont();
-        font = new Font(font.getFontName(), font.getStyle(), 8);
+        font = new Font(font.getFontName(), font.getStyle(), font.getSize() * 2/3);
         fixedTable.setFont(font);
         TableColumn col = fixedTable.getColumnModel().getColumn(0);
         col.setPreferredWidth(200);
@@ -276,7 +277,8 @@ public class AlignmentViewer extends JPanel {
         buttonBox.add(useColorCheckBox);
         dlg.add(buttonBox, BorderLayout.SOUTH);
 
-        dlg.setSize(1024, 600);
+        int size = UIManager.getFont("Label.font").getSize();
+        dlg.setSize(1024 * size / 13, 600 * size / 13);
         dlg.setModal(true);
         dlg.setVisible(true);
         dlg.dispose();
diff --git a/src/beast/app/beauti/Beauti.java b/src/beast/app/beauti/Beauti.java
index 66110c2..bb3383a 100644
--- a/src/beast/app/beauti/Beauti.java
+++ b/src/beast/app/beauti/Beauti.java
@@ -43,6 +43,7 @@ import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
 import javax.swing.JTabbedPane;
 import javax.swing.JTextArea;
+import javax.swing.UIManager;
 import javax.swing.WindowConstants;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
@@ -79,7 +80,8 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
      * current directory for opening files *
      */
     public static String g_sDir = System.getProperty("user.dir");
-    /**
+
+	/**
      * File extension for Beast specifications
      */
     static public final String FILE_EXT = ".xml";
@@ -620,7 +622,8 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
 		public void actionPerformed(ActionEvent ae) {
             setCursor(new Cursor(Cursor.WAIT_CURSOR));
             HelpBrowser b = new HelpBrowser(currentTab.config.getType());
-            b.setSize(800, 800);
+            int size = UIManager.getFont("Label.font").getSize();
+            b.setSize(800 * size / 13, 800 * size / 13);
             b.setVisible(true);
             b.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
             setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
@@ -895,6 +898,7 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
         }
 	}
 
+	
 	void setUpViewMenu() {
         m_viewPanelCheckBoxMenuItems = null;
         viewMenu.removeAll();
@@ -908,6 +912,35 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
         }
         viewMenu.addSeparator();
         viewMenu.add(a_viewall);
+        
+        viewMenu.addSeparator();
+        MyAction zoomIn = new MyAction("Zoom in", "Increase font size of all components", null, KeyEvent.VK_EQUALS) {
+ 			private static final long serialVersionUID = 1L;
+
+			@Override
+        	public void actionPerformed(ActionEvent ae) {
+				int size = UIManager.getFont("Label.font").getSize();
+            	Utils.setFontSize(size + 1);
+            	Utils.saveBeautiProperty("fontsize", (size + 1) + "");
+        		refreshPanel();
+        		repaint();
+        	}
+        };
+        MyAction zoomOut = new MyAction("Zoom out", "Decrease font size of all components", null, KeyEvent.VK_MINUS) {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+        	public void actionPerformed(ActionEvent ae) {
+				int size = UIManager.getFont("Label.font").getSize();
+            	Utils.setFontSize(Math.max(size - 1, 4));
+            	Utils.saveBeautiProperty("fontsize", Math.max(size - 1, 4) + "");
+        		refreshPanel();
+        		repaint();
+        	}
+        };
+        viewMenu.add(zoomIn);
+        viewMenu.add(zoomOut);
+
     }
 
     class TemplateAction extends AbstractAction {
@@ -1130,6 +1163,7 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
                 + "-h, -help : print this help message\n";
     }
 
+   
 
     public static Beauti main2(String[] args) {
         try {
@@ -1189,9 +1223,9 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
             }
 
             AddOnManager.loadExternalJars();
-            if (!Utils.isMac()) {
+            //if (!Utils.isMac()) {
             	Utils.loadUIManager();
-            }
+            //}
             BEASTObjectPanel.init();
 
             BeautiDoc doc = new BeautiDoc();
@@ -1201,7 +1235,7 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
             }
 
             final Beauti beauti = new Beauti(doc);
-
+            
             if (Utils.isMac()) {
                 // set up application about-menu for Mac
                 // Mac-only stuff
@@ -1295,7 +1329,8 @@ public class Beauti extends JTabbedPane implements BeautiDocListener {
             }
 
             frame.add(beauti);
-            frame.setSize(1024, 768);
+            int size = UIManager.getFont("Label.font").getSize();
+            frame.setSize(1024 * size / 13, 768 * size / 13);
             frame.setLocation(BEAUtiIntances * 10, BEAUtiIntances * 10);
             frame.setVisible(true);
 
diff --git a/src/beast/app/beauti/BeautiDoc.java b/src/beast/app/beauti/BeautiDoc.java
index e63e4d3..2d92a4f 100644
--- a/src/beast/app/beauti/BeautiDoc.java
+++ b/src/beast/app/beauti/BeautiDoc.java
@@ -1001,6 +1001,9 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider {
                 if (tree != null && tree != ((GenericTreeLikelihood) d).treeInput.get()) {
                     clockModel = clockModels.get(k);
                     Log.warning.println("WARNING: unlinking clock model for " + d.getID());
+                    // TODO #557: this should move to the event of clock model drop box
+//                    JOptionPane.showMessageDialog(beauti.getSelectedComponent(),
+//                            "Cannot link all clock model(s) except strict clock with different trees !");
                     ((GenericTreeLikelihood) d).branchRateModelInput.setValue(clockModel, d);
                 }
             } catch (Exception e) {
diff --git a/src/beast/app/beauti/BeautiSubTemplate.java b/src/beast/app/beauti/BeautiSubTemplate.java
index 6b989d2..451971c 100644
--- a/src/beast/app/beauti/BeautiSubTemplate.java
+++ b/src/beast/app/beauti/BeautiSubTemplate.java
@@ -253,7 +253,7 @@ public class BeautiSubTemplate extends BEASTObject {
         this.doc = doc;
     }
 
-    void removeSubNet(BeautiSubTemplate template, PartitionContext context)  {
+    public void removeSubNet(BeautiSubTemplate template, PartitionContext context)  {
         // disconnect all connection points in the template
         for (BeautiConnector connector : template.connectors) {
             doc.disconnect(connector, context);
diff --git a/src/beast/app/beauti/JPackageDialog.java b/src/beast/app/beauti/JPackageDialog.java
index ebcae34..afcd5f7 100644
--- a/src/beast/app/beauti/JPackageDialog.java
+++ b/src/beast/app/beauti/JPackageDialog.java
@@ -426,7 +426,8 @@ public class JPackageDialog extends JPanel {
         Point frameLocation = frame.getLocation();
         Dimension frameSize = frame.getSize();
         Dimension dim = getPreferredSize();
-		dlg.setSize(690, 430);
+        int size = UIManager.getFont("Label.font").getSize();
+        dlg.setSize(690 * size / 13, 430 * size / 13);
         dlg.setLocation(frameLocation.x + frameSize.width / 2 - dim.width / 2, frameLocation.y + frameSize.height / 2 - dim.height / 2);
 
         frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
diff --git a/src/beast/app/beauti/MRCAPriorInputEditor.java b/src/beast/app/beauti/MRCAPriorInputEditor.java
index 69cc002..35b12a0 100644
--- a/src/beast/app/beauti/MRCAPriorInputEditor.java
+++ b/src/beast/app/beauti/MRCAPriorInputEditor.java
@@ -50,8 +50,8 @@ public class MRCAPriorInputEditor extends InputEditor.Base {
         String text = prior.getID();
 
         JButton taxonButton = new JButton(text);
-        taxonButton.setMinimumSize(Base.PREFERRED_SIZE);
-        taxonButton.setPreferredSize(Base.PREFERRED_SIZE);
+//        taxonButton.setMinimumSize(Base.PREFERRED_SIZE);
+//        taxonButton.setPreferredSize(Base.PREFERRED_SIZE);
         itemBox.add(taxonButton);
         taxonButton.addActionListener(e -> {
                 List<?> list = (List<?>) m_input.get();
diff --git a/src/beast/app/beauti/ParametricDistributionInputEditor.java b/src/beast/app/beauti/ParametricDistributionInputEditor.java
index ef3a5c2..9976d49 100644
--- a/src/beast/app/beauti/ParametricDistributionInputEditor.java
+++ b/src/beast/app/beauti/ParametricDistributionInputEditor.java
@@ -15,6 +15,7 @@ import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.JComponent;
 import javax.swing.JPanel;
+import javax.swing.UIManager;
 
 import org.apache.commons.math.MathException;
 
@@ -187,7 +188,7 @@ public class ParametricDistributionInputEditor extends BEASTObjectInputEditor {
             final int NR_OF_TICKS_Y = m_nTicks;
 
             // draw ticks on edge
-            Font smallFont = new Font(font.getName(), font.getStyle(), 8);
+            Font smallFont = new Font(font.getName(), font.getStyle(), font.getSize() * 2/3);
             g.setFont(smallFont);
 
             // collect the ylabels and the maximum label width in small font
@@ -247,7 +248,7 @@ public class ParametricDistributionInputEditor extends BEASTObjectInputEditor {
                 g.drawString(ylabels[i], leftMargin - TICK_LENGTH - 1 - sfm.stringWidth(ylabels[i]), y + 3);
             }
 
-            g.setFont(new Font(font.getName(), font.getStyle(), 10));
+            g.setFont(new Font(font.getName(), font.getStyle(), font.getSize() * 10 / 12));
             try {
                 FontMetrics fontMetrics = g.getFontMetrics();
                 String[] strs = new String[]{"2.5% Quantile", "5% Quantile", "Median", "95% Quantile", "97.5% Quantile"};
@@ -337,7 +338,8 @@ public class ParametricDistributionInputEditor extends BEASTObjectInputEditor {
 
     private Component createGraph() {
         JPanel panel = new PDPanel();
-        Dimension size = new Dimension(200, 200);
+        int fsize = UIManager.getFont("Label.font").getSize();
+        Dimension size = new Dimension(200 * fsize / 13, 200 * fsize / 13);
         panel.setSize(size);
         panel.setPreferredSize(size);
         panel.setMinimumSize(size);
diff --git a/src/beast/app/beauti/PriorInputEditor.java b/src/beast/app/beauti/PriorInputEditor.java
index f74cfd3..9d9060a 100644
--- a/src/beast/app/beauti/PriorInputEditor.java
+++ b/src/beast/app/beauti/PriorInputEditor.java
@@ -1,6 +1,7 @@
 package beast.app.beauti;
 
 import java.awt.Dimension;
+import java.awt.Font;
 import java.util.Arrays;
 import java.util.List;
 
@@ -8,6 +9,7 @@ import javax.swing.Box;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
+import javax.swing.JPanel;
 
 import beast.app.draw.BEASTObjectDialog;
 import beast.app.draw.InputEditor;
@@ -41,8 +43,10 @@ public class PriorInputEditor extends InputEditor.Base {
         Prior prior = (Prior) beastObject;
         String text = prior.getParameterName();
         JLabel label = new JLabel(text);
-        label.setMinimumSize(PREFERRED_SIZE);
-        label.setPreferredSize(PREFERRED_SIZE);
+        Font font = label.getFont();
+        Dimension size = new Dimension(font.getSize() * 200 / 13, font.getSize() * 25/13);
+        label.setMinimumSize(size);
+        label.setPreferredSize(size);
         itemBox.add(label);
 
         List<BeautiSubTemplate> availableBEASTObjects = doc.getInputEditorFactory().getAvailableTemplates(prior.distInput, prior, null, doc);
@@ -77,8 +81,11 @@ public class PriorInputEditor extends InputEditor.Base {
             sync();
             refreshPanel();
         });
-        itemBox.add(comboBox);
-
+        JPanel panel = new JPanel();
+        panel.add(comboBox);
+        panel.setMaximumSize(size);
+        itemBox.add(panel);
+        
         if (prior.m_x.get() instanceof RealParameter) {
             // add range button for real parameters
             RealParameter p = (RealParameter) prior.m_x.get();
diff --git a/src/beast/app/beauti/TaxonSetDialog.java b/src/beast/app/beauti/TaxonSetDialog.java
index d654bfa..2b72d14 100644
--- a/src/beast/app/beauti/TaxonSetDialog.java
+++ b/src/beast/app/beauti/TaxonSetDialog.java
@@ -20,6 +20,7 @@ import javax.swing.JList;
 import javax.swing.JOptionPane;
 import javax.swing.JScrollPane;
 import javax.swing.JTextField;
+import javax.swing.UIManager;
 import javax.swing.border.EmptyBorder;
 import javax.swing.border.EtchedBorder;
 import javax.swing.event.DocumentEvent;
@@ -82,7 +83,8 @@ public class TaxonSetDialog extends JDialog {
         }
 
         add(box);
-        setSize(new Dimension(400, 600));
+        int size = UIManager.getFont("Label.font").getSize();
+        setSize(400 * size / 13, 600 * size / 13);
         setModal(true);
     } // c'tor
     
diff --git a/src/beast/app/beauti/TipDatesInputEditor.java b/src/beast/app/beauti/TipDatesInputEditor.java
index bd656f7..55d638e 100644
--- a/src/beast/app/beauti/TipDatesInputEditor.java
+++ b/src/beast/app/beauti/TipDatesInputEditor.java
@@ -359,7 +359,8 @@ public class TipDatesInputEditor extends BEASTObjectInputEditor {
             public void addCellEditorListener(CellEditorListener l) {
             }
         });
-        table.setRowHeight(24);
+        int fontsize = table.getFont().getSize();
+        table.setRowHeight(24 * fontsize / 13);
         scrollPane = new JScrollPane(table);
 
 // AJD: This ComponentListener breaks the resizing of the tip dates table, so I have removed it.
@@ -544,7 +545,9 @@ public class TipDatesInputEditor extends BEASTObjectInputEditor {
                     ex.printStackTrace();
                 }
             });
+        Dimension d = unitsComboBox.getPreferredSize();
         unitsComboBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, unitsComboBox.getPreferredSize().height));
+        unitsComboBox.setSize(d);
         buttonBox.add(unitsComboBox);
 
         relativeToComboBox = new JComboBox<>(new String[]{"Since some time in the past", "Before the present"});
diff --git a/src/beast/app/beauti/TreeDistributionInputEditor.java b/src/beast/app/beauti/TreeDistributionInputEditor.java
index 528eebc..80d47e9 100644
--- a/src/beast/app/beauti/TreeDistributionInputEditor.java
+++ b/src/beast/app/beauti/TreeDistributionInputEditor.java
@@ -1,6 +1,8 @@
 package beast.app.beauti;
 
 import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.event.ActionEvent;
 import java.util.List;
 
@@ -59,8 +61,10 @@ public class TreeDistributionInputEditor extends InputEditor.Base {
             text += distr.treeIntervalsInput.get().treeInput.get().getID();
         }
         JLabel label = new JLabel(text);
-        label.setMinimumSize(Base.PREFERRED_SIZE);
-        label.setPreferredSize(Base.PREFERRED_SIZE);
+        Font font = label.getFont();
+        Dimension size = new Dimension(font.getSize() * 200 / 12, font.getSize() * 2);
+        label.setMinimumSize(size);
+        label.setPreferredSize(size);
         itemBox.add(label);
         // List<String> availableBEASTObjects =
         // PluginPanel.getAvailablePlugins(m_input, m_beastObject, null);
diff --git a/src/beast/app/draw/BEASTObjectShape.java b/src/beast/app/draw/BEASTObjectShape.java
index 0802ce0..5a6c9ca 100644
--- a/src/beast/app/draw/BEASTObjectShape.java
+++ b/src/beast/app/draw/BEASTObjectShape.java
@@ -36,6 +36,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.swing.JPanel;
+import javax.swing.UIManager;
 
 import org.w3c.dom.Node;
 
@@ -48,7 +49,7 @@ import beast.util.Randomizer;
 
 
 public class BEASTObjectShape extends Shape {
-    static Font g_PluginFont = new Font("arial", Font.PLAIN, 11);
+    static Font g_PluginFont = new Font("arial", Font.PLAIN, UIManager.getFont("Label.font").getSize() * 11 / 12);
     public beast.core.BEASTInterface m_beastObject;
     List<InputShape> m_inputs;
 
diff --git a/src/beast/app/draw/HelpBrowser.java b/src/beast/app/draw/HelpBrowser.java
index 586d32e..cd0439b 100644
--- a/src/beast/app/draw/HelpBrowser.java
+++ b/src/beast/app/draw/HelpBrowser.java
@@ -33,6 +33,7 @@ import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JEditorPane;
 import javax.swing.JScrollPane;
+import javax.swing.UIManager;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 
@@ -179,7 +180,8 @@ public class HelpBrowser extends JDialog implements HyperlinkListener {
     public static void main(String[] args) {
         try {
             HelpBrowser b = new HelpBrowser("beast.core.MCMC");
-            b.setSize(800, 800);
+            int size = UIManager.getFont("Label.font").getSize();
+            b.setSize(800 * size / 13, 800 * size / 13);
             b.setVisible(true);
             b.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
         } catch (Exception e) {
diff --git a/src/beast/app/draw/InputEditor.java b/src/beast/app/draw/InputEditor.java
index 1c255d0..7c6126a 100644
--- a/src/beast/app/draw/InputEditor.java
+++ b/src/beast/app/draw/InputEditor.java
@@ -218,13 +218,15 @@ public abstract class Base extends JPanel implements InputEditor {
     void setUpEntry() {
         m_entry = new JTextField();
         m_entry.setName(m_input.getName());
-        Dimension prefDim = new Dimension(PREFERRED_SIZE.width, m_entry.getPreferredSize().height);
-        Dimension maxDim = new Dimension(MAX_SIZE.width, m_entry.getPreferredSize().height);
-        m_entry.setMinimumSize(prefDim);
-        m_entry.setPreferredSize(prefDim);
-        m_entry.setSize(prefDim);
+        m_entry.setColumns(10);
+//        Dimension prefDim = new Dimension(PREFERRED_SIZE.width, m_entry.getPreferredSize().height);
+//        Dimension maxDim = new Dimension(MAX_SIZE.width, m_entry.getPreferredSize().height);
+//        m_entry.setMinimumSize(prefDim);
+//        m_entry.setPreferredSize(prefDim);
+//        m_entry.setSize(prefDim);
         initEntry();
         m_entry.setToolTipText(m_input.getHTMLTipText());
+        Dimension maxDim = m_entry.getPreferredSize();
         m_entry.setMaximumSize(maxDim);
 
         m_entry.getDocument().addDocumentListener(new DocumentListener() {
@@ -312,7 +314,8 @@ public abstract class Base extends JPanel implements InputEditor {
             m_inputLabel.setToolTipText(tipText);
             m_inputLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
             //Dimension size = new Dimension(g_nLabelWidth, 20);
-            Dimension size = new Dimension(200, 20);
+            int fontsize = m_inputLabel.getFont().getSize();
+            Dimension size = new Dimension(200, 20 * fontsize / 13);
             m_inputLabel.setMaximumSize(size);
             m_inputLabel.setMinimumSize(size);
             m_inputLabel.setPreferredSize(size);
diff --git a/src/beast/app/draw/IntegerListInputEditor.java b/src/beast/app/draw/IntegerListInputEditor.java
index 2db8057..7eef756 100644
--- a/src/beast/app/draw/IntegerListInputEditor.java
+++ b/src/beast/app/draw/IntegerListInputEditor.java
@@ -186,12 +186,13 @@ public class IntegerListInputEditor extends ListInputEditor {
 		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);
+            m_entry.setColumns(6);
+//            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.setMaximumSize(MAX_SIZE);
 
             m_entry.getDocument().addDocumentListener(new DocumentListener() {
                 @Override
diff --git a/src/beast/app/draw/ModelBuilder.java b/src/beast/app/draw/ModelBuilder.java
index 116b805..625a3b4 100644
--- a/src/beast/app/draw/ModelBuilder.java
+++ b/src/beast/app/draw/ModelBuilder.java
@@ -74,6 +74,7 @@ import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
 import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
+import javax.swing.UIManager;
 import javax.swing.filechooser.FileFilter;
 
 import beast.app.util.Utils;
@@ -1274,7 +1275,8 @@ public class ModelBuilder extends JPanel implements ComponentListener {
 
     public void init() {
         m_Selection.setDocument(m_doc);
-        setSize(2048, 2048);
+        int size = UIManager.getFont("Label.font").getSize();
+        setSize(2048 * size / 13, 2048 * size / 13);
         g_panel = new DrawPanel();
         m_jScrollPane = new JScrollPane(g_panel);
         makeToolbar();
@@ -2177,7 +2179,8 @@ public class ModelBuilder extends JPanel implements ComponentListener {
             drawTest.m_doc.loadFile(args[0]);
             drawTest.setDrawingFlag();
         }
-        f.setSize(600, 800);
+        int size = UIManager.getFont("Label.font").getSize();
+        f.setSize(800 * size / 13, 600 * size / 13);
         f.setVisible(true);
     } // main
 
diff --git a/src/beast/app/tools/AppStore.java b/src/beast/app/tools/AppStore.java
index e33b650..31e5f6c 100644
--- a/src/beast/app/tools/AppStore.java
+++ b/src/beast/app/tools/AppStore.java
@@ -32,6 +32,7 @@ import javax.swing.JScrollPane;
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.w3c.dom.Document;
@@ -92,7 +93,8 @@ public class AppStore {
 //      Dimension dim = panel.getPreferredSize();
 //      Dimension dim2 = buttonBox.getPreferredSize();
 //		setSize(dim.width + 10, dim.height + dim2.height + 30);
-        mainDialog.setSize(new Dimension(660, 400));
+        int size = UIManager.getFont("Label.font").getSize();
+        mainDialog.setSize(600 * size / 13, 400 * size / 13);
         mainDialog.setLocationRelativeTo(null);
 
         return mainDialog;
@@ -422,6 +424,7 @@ public class AppStore {
         AppStore appStore = new AppStore();
 
         if (args.length == 0) {
+        	Utils.loadUIManager();
             SwingUtilities.invokeLater(() -> appStore.launchGUI().setVisible(true));
         } else {
 
diff --git a/src/beast/app/tools/EBSPAnalyser.java b/src/beast/app/tools/EBSPAnalyser.java
index d5c21bb..dcf04be 100644
--- a/src/beast/app/tools/EBSPAnalyser.java
+++ b/src/beast/app/tools/EBSPAnalyser.java
@@ -20,6 +20,7 @@ import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.UIManager;
 import javax.swing.border.EmptyBorder;
 
 import beast.app.BEASTVersion2;
@@ -276,7 +277,8 @@ public class EBSPAnalyser {
             final JLabel titleText = new JLabel(titleString);
             titleText.setIcon(icon);
             optionPanel.addSpanningComponent(titleText);
-            titleText.setFont(new Font("sans-serif", 0, 12));
+            Font font = UIManager.getFont("Label.font");
+            titleText.setFont(new Font("sans-serif", font.getStyle(), font.getSize()));
 
             JPanel panel = new JPanel(new BorderLayout());
             panel.setOpaque(false);
@@ -393,7 +395,9 @@ public class EBSPAnalyser {
         try {
             EBSPAnalyser analyser = new EBSPAnalyser();
             if (args.length == 0) {
-                System.setProperty("com.apple.macos.useScreenMenuBar", "true");
+            	Utils.loadUIManager();
+
+            	System.setProperty("com.apple.macos.useScreenMenuBar", "true");
                 System.setProperty("apple.laf.useScreenMenuBar", "true");
                 System.setProperty("apple.awt.showGrowBox", "true");
 
diff --git a/src/beast/app/tools/LogCombiner.java b/src/beast/app/tools/LogCombiner.java
index b74d1a7..decf417 100644
--- a/src/beast/app/tools/LogCombiner.java
+++ b/src/beast/app/tools/LogCombiner.java
@@ -18,6 +18,7 @@ import javax.swing.JFrame;
 import javax.swing.table.TableCellEditor;
 
 import beast.app.BEASTVersion2;
+import beast.app.util.Utils;
 import beast.core.util.Log;
 import beast.util.LogAnalyser;
 import jam.console.ConsoleApplication;
@@ -36,17 +37,20 @@ public class LogCombiner extends LogAnalyser {
     PrintStream m_out = System.out;
     int m_nBurninPercentage = 10;
 
+    private boolean preAmpleIsPrinted = false;
+    private int columnCount = -1;
+
     boolean m_bIsTreeLog = false;
     List<String> m_sTrees;
     // Sample interval as it appears in the combined log file.
     // To use the interval of the log files, use the -renumber option
-    int m_nSampleInterval = 1;
+    int m_nSampleInterval = -1;
     // whether to use decimal or scientific format to print doubles
     boolean m_bUseDecimalFormat = false;
     DecimalFormat format = new DecimalFormat("#.############E0", new DecimalFormatSymbols(Locale.US));
 
     // resample the log files to this frequency (the original sampling frequency must be a factor of this value)
-    int m_nResample = 1;
+    int m_nResample = -1;
 
     private void parseArgs(String[] args) {
         int i = 0;
@@ -92,7 +96,7 @@ public class LogCombiner extends LogAnalyser {
                         m_nResample = Integer.parseInt(args[i + 1]);
                         i += 2;
                     } else if (args[i].equals("-renumber")) {
-                        m_nSampleInterval = -1;
+                        m_nSampleInterval = 1;
                         i++;
                     }
                     if (i == old) {
@@ -134,58 +138,137 @@ public class LogCombiner extends LogAnalyser {
 		}
     }
 
+    @SuppressWarnings("unchecked")
+	protected long readLogFile(String fileName, int burnInPercentage, long state) throws IOException {
+        log("\nLoading " + fileName);
+        BufferedReader fin = new BufferedReader(new FileReader(fileName));
+        String str;
+        m_sPreAmble = "";
+        m_sLabels = null;
+        int data = 0;
+        // first, sweep through the log file to determine size of the log
+        while (fin.ready()) {
+            str = fin.readLine();
+            if (str.indexOf('#') < 0 && str.matches(".*[0-9a-zA-Z].*")) {
+                if (m_sLabels == null)
+                    m_sLabels = str.split("\\s");
+                else
+                    data++;
+            } else {
+                m_sPreAmble += str + "\n";
+            }
+        }
+        if (!preAmpleIsPrinted) {
+        	m_out.print(m_sPreAmble);
+            // header
+            for (int i = 0; i < m_sLabels.length; i++) {
+                m_out.print(m_sLabels[i] + "\t");
+            }
+            m_out.println();
+        	preAmpleIsPrinted = true;
+        }
+        
+        int lines = Math.max(1, data / 80);
+        // reserve memory
+        int items = m_sLabels.length;
+        m_ranges = new List[items];
+        int burnIn = data * burnInPercentage / 100;
+        m_fTraces = new Double[items][data - burnIn];
+        fin.close();
+        fin = new BufferedReader(new FileReader(fileName));
+        data = -burnIn - 1;
+        logln(", burnin " + burnInPercentage + "%, skipping " + burnIn + " log lines\n\n" + BAR);
+        // grab data from the log, ignoring burn in samples
+        long prevLogState = -1;
+        while (fin.ready()) {
+            str = fin.readLine();
+            if (str.indexOf('#') < 0 && str.matches("[0-9].*")) {
+                data++;
+                if (data >= 0) {
+                	String [] strs = str.split("\\s");
+                	long logState = Long.parseLong(strs[0]);
+                    if (m_nSampleInterval < 0 && prevLogState >= 0) {
+                        // need to renumber
+                    	if (m_nResample < 0) {
+                    		m_nSampleInterval = (int) (logState - prevLogState);
+                    	} else {
+                    		m_nSampleInterval = m_nResample;
+                    	}
+                    }
+                    prevLogState = logState;
+                    if (columnCount != strs.length) {
+                    	if (columnCount < 0) {
+                    		columnCount = strs.length;
+                    	} else {
+                            fin.close();
+                            throw new IllegalArgumentException("ERROR: The number of columns in file " + fileName + " does not match that of the first file");
+                    	}
+                    }
+                	
+                	if (logState % m_nResample == 0 || m_nResample < 0) {
+	                	if (state < 0) {
+	                		state = 0;
+	                	} else {
+	                		state += m_nSampleInterval;
+	                	}
+	                	m_out.print(state + "\t");
+	                	for (int k = 1; k < strs.length; k++) {
+		                	if (m_bUseDecimalFormat && strs[k].indexOf('.') > 0) {
+		                		double d = Double.parseDouble(strs[k]);
+		                		m_out.print(format.format(d));
+		                	} else {
+		                		m_out.print(strs[k]);
+		                	}
+	                		m_out.print('\t');
+	                	}
+	                	m_out.println();
+                	}
+                }
+        	}
+            if (data % lines == 0) {
+                log("*");
+            }
+        }
+        logln("");
+        fin.close();
+        return state;
+    } // readLogFile
+
+
     private void combineLogs(String[] logs, int[] burbIns) throws IOException {
+    	preAmpleIsPrinted = false;
+        log("Writing to file " + m_sFileOut);
+        try {
+            m_out = new PrintStream(new File(m_sFileOut));
+        } catch (FileNotFoundException e) {
+            log("Could not open file " + m_sFileOut + " for writing: " + e.getMessage());
+            return;
+        }
+
         m_fCombinedTraces = null;
-        // read logs
-        int columns = 0;
+        // process logs
         int k = 0;
+        long state = -1;
         for (String fileName : logs) {
             BufferedReader fin = new BufferedReader(new FileReader(fileName));
             String str = fin.readLine();
             if (str.toUpperCase().startsWith("#NEXUS")) {
                 m_bIsTreeLog = true;
-                readTreeLogFile(fileName, burbIns[k]);
+                state = readTreeLogFile(fileName, burbIns[k], state);
             } else {
-                readLogFile(fileName, burbIns[k]);
-            }
-
-            if (m_fCombinedTraces == null) {
-                m_fCombinedTraces = m_fTraces;
-                if (!m_bIsTreeLog) {
-                    columns = m_sLabels.length;
-                }
-            } else {
-                if (columns != m_sLabels.length) {
-                    fin.close();
-                    throw new IllegalArgumentException("ERROR: The number of columns in file " + fileName + " does not match that of the first file");
-                }
-                for (int i = 0; i < m_fTraces.length; i++) {
-                    Double[] logLine = m_fTraces[i];
-                    Double[] oldTrace = m_fCombinedTraces[i];
-                    Double[] newTrace = new Double[oldTrace.length + logLine.length];
-                    System.arraycopy(oldTrace, 0, newTrace, 0, oldTrace.length);
-                    System.arraycopy(logLine, 0, newTrace, oldTrace.length, logLine.length);
-                    m_fCombinedTraces[i] = newTrace;
-                }
+                state = readLogFile(fileName, burbIns[k], state);
             }
             k++;
             fin.close();
         }
-        if (!m_bIsTreeLog) {
-            // reset sample column
-            if (m_fCombinedTraces[0].length > 2) {
-                if (m_nSampleInterval < 0) {
-                    // need to renumber
-                    m_nSampleInterval = (int) (m_fCombinedTraces[0][1] - m_fCombinedTraces[0][0]);
-                }
-                for (int i = 0; i < m_fCombinedTraces[0].length; i++) {
-                    m_fCombinedTraces[0][i] = (double) (m_nSampleInterval * i);
-                }
-            }
+        if (m_bIsTreeLog) {
+        	m_out.println("End;");
         }
+        m_out.close();
+        log("Wrote " + (state/m_nSampleInterval + 1) + " lines to " + m_sFileOut);
     }
 
-    protected void readTreeLogFile(String fileName, int burnInPercentage) throws IOException {
+    protected long readTreeLogFile(String fileName, int burnInPercentage, long state) throws IOException {
         log("\nLoading " + fileName);
         BufferedReader fin = new BufferedReader(new FileReader(fileName));
         String str = null;
@@ -202,6 +285,10 @@ public class LogCombiner extends LogAnalyser {
                 }
             }
         }
+        if (!preAmpleIsPrinted) {
+        	m_out.println(m_sPreAmble);
+        	preAmpleIsPrinted = true;
+        }
         int lines = data / 80;
         // reserve memory
         int burnIn = data * burnInPercentage / 100;
@@ -212,25 +299,36 @@ public class LogCombiner extends LogAnalyser {
         fin.close();
         fin = new BufferedReader(new FileReader(fileName));
         data = -burnIn - 1;
-        // grab data from the log, ignoring burn in samples
-        int sample0 = -1;
 
+        // grab data from the log, ignoring burn in samples
+        long prevLogState = -1;
         while (fin.ready()) {
             str = fin.readLine();
             if (str.matches("^tree STATE_.*")) {
                 if (++data >= 0) {
-                    if (m_nSampleInterval < 0) {
-                        String str2 = str.substring(11, str.indexOf("=")).trim();
-                        str2 = str2.split("\\s")[0];
-                        if (sample0 < 0) {
-                            sample0 = Integer.parseInt(str2);
-                        } else {
-                            m_nSampleInterval = Integer.parseInt(str2) - sample0;
-                        }
-
-                    }
-                    str = str.replaceAll("^tree STATE_[^\\s=]*", "");
-                    m_sTrees.add(str);
+                    String str2 = str.substring(11, str.indexOf("=")).trim();
+                    str2 = str2.split("\\s")[0];
+                    long logState = Long.parseLong(str2);
+                    if (m_nSampleInterval < 0 && prevLogState >= 0) {
+                        // need to renumber
+                    	if (m_nResample < 0) {
+                    		m_nSampleInterval = (int) (logState - prevLogState);
+                    	} else {
+                    		m_nSampleInterval = m_nResample;
+                    	}
+                   }
+                    prevLogState = logState;
+                	
+                	if (logState % m_nResample == 0 || m_nResample < 0) {
+	                	if (state < 0) {
+	                		state = 0;
+	                	} else {
+	                		state += m_nSampleInterval;
+	                	}
+	                    str = str.replaceAll("^tree STATE_[^\\s=]*", "");
+	                	m_out.print("tree STATE_" + state + " =" + str);
+	                	m_out.println();
+                	}
                 }
             }
             if (data % lines == 0) {
@@ -238,6 +336,7 @@ public class LogCombiner extends LogAnalyser {
             }
         }
         logln("");
+        return state;
     } // readTreeLogFile
 
     private void printCombinedLogs() {
@@ -376,12 +475,12 @@ public class LogCombiner extends LogAnalyser {
                 "options:\n" +
                 "-log <file>      specify the name of the log file, each log file must be specified with separate -log option\n" +
                 "-o <output.log>  specify log file to write into (default output is stdout)\n" +
-                "-b <burnin>      specify the number PERCANTAGE of lines in the log file considered to be burnin (default 10)\n" +
-                "-dir <directory> specify particle directory -- used for particle filtering in BEASTii only -- if defined only one log must be specified and the -n option specified\n" +
+                "-b <burnin>      specify the number PERCENTAGE of lines in the log file considered to be burnin (default 10)\n" +
+                "-dir <directory> specify particle directory -- used for particle filtering in BEASTLabs only -- if defined only one log must be specified and the -n option specified\n" +
                 "-n <int>         specify the number of particles, ignored if -dir is not defined\n" +
                 "-resample <int>  specify number of states to resample\n" +
                 "-decimal         flag to indicate numbers should converted from scientific into decimal format\n" +
-                "-renumber        flag to indicate ouput states should be renumbered\n" +
+                "-renumber        flag to indicate output states should be renumbered\n" +
                 "-help            print this message\n";
     }
 
@@ -423,6 +522,8 @@ public class LogCombiner extends LogAnalyser {
         LogCombiner combiner = new LogCombiner();
         try {
             if (args.length == 0) {
+            	Utils.loadUIManager();
+
                 System.setProperty("com.apple.macos.useScreenMenuBar", "true");
                 System.setProperty("apple.laf.useScreenMenuBar", "true");
                 System.setProperty("apple.awt.showGrowBox", "true");
@@ -480,8 +581,7 @@ public class LogCombiner extends LogAnalyser {
 
                 try {
                     combiner.combineLogs(inputFiles, burnins);
-                    combiner.printCombinedLogs();
-
+ 
                 } catch (Exception ex) {
                 	Log.warning.println("Exception: " + ex.getMessage());
                     ex.printStackTrace();
@@ -508,8 +608,8 @@ public class LogCombiner extends LogAnalyser {
                 } else {
                     // particle log combiner
                     combiner.combineParticleLogs();
+                    combiner.printCombinedLogs();
                 }
-                combiner.printCombinedLogs();
             }
         } catch (Exception e) {
             System.out.println(getUsage());
diff --git a/src/beast/app/tools/LogCombinerDialog.java b/src/beast/app/tools/LogCombinerDialog.java
index 0b47859..680e25b 100644
--- a/src/beast/app/tools/LogCombinerDialog.java
+++ b/src/beast/app/tools/LogCombinerDialog.java
@@ -102,7 +102,8 @@ public class LogCombinerDialog {
         final JLabel titleText = new JLabel(titleString);
         titleText.setIcon(icon);
         optionPanel.addSpanningComponent(titleText);
-        titleText.setFont(new Font("sans-serif", 0, 12));
+        Font font = UIManager.getFont("Label.font");
+        titleText.setFont(new Font("sans-serif", font.getStyle(), font.getSize()));
 
         JPanel panel = new JPanel(new BorderLayout());
         panel.setOpaque(false);
diff --git a/src/beast/app/treeannotator/TreeAnnotator.java b/src/beast/app/treeannotator/TreeAnnotator.java
index 0c0e218..b16aca7 100644
--- a/src/beast/app/treeannotator/TreeAnnotator.java
+++ b/src/beast/app/treeannotator/TreeAnnotator.java
@@ -49,6 +49,7 @@ import beast.app.BEASTVersion;
 import beast.app.beauti.BeautiDoc;
 import beast.app.tools.LogCombiner;
 import beast.app.util.Arguments;
+import beast.app.util.Utils;
 import beast.core.util.Log;
 import beast.evolution.alignment.TaxonSet;
 import beast.evolution.tree.Node;
@@ -554,13 +555,13 @@ public class TreeAnnotator {
         progressStream.println("0              25             50             75            100");
         progressStream.println("|--------------|--------------|--------------|--------------|");
 
-        stepSize = Math.max(totalTrees / 60, 1);
+        stepSize = Math.max(totalTreesUsed / 60, 1);
         int reported = 0;
 
         // this call increments the clade counts and it shouldn't
         // this is remedied with removeClades call after while loop below
         cladeSystem = new CladeSystem(targetTree);
-        totalTreesUsed = 0;
+        int totalTreesUsed = 0;
         try {
             int counter = 0;
             treeSet.reset();
@@ -571,9 +572,11 @@ public class TreeAnnotator {
             	}
                 cladeSystem.collectAttributes(tree, attributeNames);
                 if (counter > 0 && counter % stepSize == 0 && reported < 61) {
-                    progressStream.print("*");
+    				while (1000 * reported < 61000 * (counter + 1)/ this.totalTreesUsed) {
+    	                progressStream.print("*");
+    	                reported++;
+            	    }
                     progressStream.flush();
-                    reported++;
                 }
                 totalTreesUsed++;
                 counter++;
@@ -581,6 +584,7 @@ public class TreeAnnotator {
         	
             cladeSystem.removeClades(targetTree.getRoot(), true);
             //progressStream.println("totalTreesUsed=" + totalTreesUsed);
+            this.totalTreesUsed = totalTreesUsed;
             cladeSystem.calculateCladeCredibilities(totalTreesUsed);
         } catch (Exception e) {
             Log.err.println("Error Parsing Input Tree: " + e.getMessage());
@@ -686,7 +690,7 @@ public class TreeAnnotator {
         progressStream.println("0              25             50             75            100");
         progressStream.println("|--------------|--------------|--------------|--------------|");
 
-        int stepSize = Math.max(totalTrees / 60, 1);
+        int stepSize = Math.max(totalTreesUsed / 60, 1);
         int reported = 0;
 
         int counter = 0;
@@ -698,10 +702,12 @@ public class TreeAnnotator {
               bestTree = tree;
               bestScore = score;
           }
-          if (counter > 0 && counter % stepSize == 0 && reported < 61) {
-              progressStream.print("*");
+          if (counter % stepSize == 0 && reported < 61) {
+			  while (1000*reported < 61000 * (counter + 1) / totalTreesUsed) {
+	              progressStream.print("*");
+	              reported++;
+        	  }
               progressStream.flush();
-              reported++;
           }
           counter++;
         }
@@ -1258,6 +1264,8 @@ public class TreeAnnotator {
         String outputFileName = null;
 
         if (args.length == 0) {
+        	Utils.loadUIManager();
+
             System.setProperty("com.apple.macos.useScreenMenuBar", "true");
             System.setProperty("apple.laf.useScreenMenuBar", "true");
             System.setProperty("apple.awt.showGrowBox", "true");
@@ -1486,7 +1494,7 @@ public class TreeAnnotator {
         progressStream.println("0              25             50             75            100");
         progressStream.println("|--------------|--------------|--------------|--------------|");
 
-        int reportStepSize = totalTrees / 60;
+        int reportStepSize = totalTreesUsed / 60;
         if (reportStepSize < 1) reportStepSize = 1;
         int reported = 0;
 
@@ -1514,7 +1522,7 @@ public class TreeAnnotator {
         // heights total sum from posterior trees
         double[] ths = new double[clades];
 
-        totalTreesUsed = 0;
+        int totalTreesUsed = 0;
 
         int counter = 0;
         treeSet.reset();
@@ -1535,9 +1543,11 @@ public class TreeAnnotator {
             }
             totalTreesUsed += 1;
             if (counter > 0 && counter % reportStepSize == 0 && reported < 61) {
-                progressStream.print("*");
+				while (1000 * reported < 61000 * (counter + 1)/ this.totalTreesUsed) {
+				    progressStream.print("*");
+				    reported++;
+				}
                 progressStream.flush();
-                reported++;
             }
             counter++;
 
@@ -1550,6 +1560,8 @@ public class TreeAnnotator {
             node.setHeight(ths[k]);
         }
 
+        assert (totalTreesUsed == this.totalTreesUsed);
+        this.totalTreesUsed = totalTreesUsed;
         progressStream.println();
         progressStream.println();
 
diff --git a/src/beast/app/util/Utils.java b/src/beast/app/util/Utils.java
index 2982456..c54b13f 100644
--- a/src/beast/app/util/Utils.java
+++ b/src/beast/app/util/Utils.java
@@ -8,6 +8,8 @@ import java.awt.Image;
 import java.awt.Toolkit;
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
@@ -15,6 +17,7 @@ import java.io.InputStreamReader;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.HashSet;
+import java.util.Properties;
 import java.util.Set;
 
 import javax.swing.ImageIcon;
@@ -94,7 +97,7 @@ public class Utils {
 
 
     public static void loadUIManager() {
-
+    	   	
         if (isMac()) {
             System.setProperty("apple.awt.graphics.UseQuartz", "true");
             System.setProperty("apple.awt.antialiasing", "true");
@@ -141,7 +144,26 @@ public class Utils {
                 }
             }
 
+        } else {
+            try {
+                // Set System L&F
+            	// this is supposed to look OK on high res screens
+            	UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+
+            } catch (UnsupportedLookAndFeelException |ClassNotFoundException | InstantiationException |IllegalAccessException e) {
+            	Log.warning.println(e.getMessage());
+            }
         }
+        
+    	// change font size, if specified in beauti.properties file
+    	String fontsize = getBeautiProperty("fontsize");
+    	if (fontsize != null) {
+    		try {
+    			setFontSize(Integer.parseInt(fontsize));
+    		} catch (NumberFormatException e) {
+    			// ignore if fontsize is improperly formatted.
+    		}
+    	}
 
 // APART FROM THE ABOVE CODE FOR OLD MAC OS X, WE SHOULD LEAVE THE UIManager to the defaults, rather than mess it up
 // DEFAULT is almost always the most appropriate thing to use!
@@ -365,4 +387,79 @@ public class Utils {
 		System.exit(0);
 	}
 
+	static public void setFontSize(int fontSize) {
+	     // Setup font size based on screen size
+		for (String item : new String[]{"Button.font", "ToggleButton.font", "RadioButton.font", 
+				"ColorChooser.font", "List.font", "MenuBar.font", "MenuItem.font", 
+				"RadioButtonMenuItem.font", "CheckBoxMenuItem.font", "Menu.font", "PopupMenu.font", "OptionPane.font", 
+				"Panel.font", "ProgressBar.font", "ScrollPane.font", "Viewport.font", "TabbedPane.font",  
+				"TableHeader.font", "PasswordField.font", 
+				"EditorPane.font", "TitledBorder.font", "ToolBar.font", "ToolTip.font", "Tree.font",
+				"ComboBox.font", "CheckBox.font", "Label.font", "Table.font", "TextField.font", "TextArea.font", "TextPane.font"}) {
+			Font font = UIManager.getFont(item);
+			UIManager.put(item, new Font(font.getName(), font.getStyle(), fontSize));
+		}
+	    Log.debug.println("Font is now at size " + fontSize);
+	}
+
+	
+	/**
+	 * Get value from beauti.properties file
+	 */
+	static public String getBeautiProperty(String key) {
+        File beastProps = new File(AddOnManager.getPackageUserDir() + "/beauti.properties");
+        if (beastProps.exists()) {
+            Properties props = new Properties();
+
+            try {
+                //load a properties file
+                props.load(new FileInputStream(beastProps));
+                return props.getProperty(key);
+
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return null;
+	}
+	
+	/**
+	 * Set property value in beauti.properties file
+	 * if value == null, the property will be removed
+	 */
+	static public void saveBeautiProperty(String key, String value) {
+        File propsFile = new File(AddOnManager.getPackageUserDir() + "/beauti.properties");
+        Properties prop = new Properties();
+
+        //Load or create properties file
+        if (propsFile.exists()) {
+            try {
+                prop.load(new FileInputStream(propsFile));
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        } else {
+            try {
+                propsFile.createNewFile();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        
+        // set or remove value
+        if (value != null) {
+        	prop.setProperty(key, value);
+        } else {
+        	prop.remove(key);
+        }
+        
+        // Write properties file
+        try {
+            prop.store(new FileOutputStream(propsFile),
+                    "Automatically-generated by BEAUti.\n");
+        } catch (IOException ex) {
+            Log.err(ex.getMessage());
+        }
+	}
+	
 }
diff --git a/src/beast/core/BEASTInterface.java b/src/beast/core/BEASTInterface.java
index 05b6312..fe45033 100644
--- a/src/beast/core/BEASTInterface.java
+++ b/src/beast/core/BEASTInterface.java
@@ -37,6 +37,12 @@ import java.util.Map;
 import java.util.Set;
 
 public interface BEASTInterface {
+	/**
+	 * initAndValidate is supposed to check validity of values of inputs, and initialise. 
+	 * If for some reason this fails, the most appropriate exception to throw is 
+	 * IllegalArgumentException (if the combination of input values is not correct)
+	 * or otherwise a RuntimeException.
+	 */	
     public void initAndValidate();
 
 	/** identifiable **/
diff --git a/src/beast/core/BEASTObject.java b/src/beast/core/BEASTObject.java
index 846fea3..6a0cd6f 100644
--- a/src/beast/core/BEASTObject.java
+++ b/src/beast/core/BEASTObject.java
@@ -89,7 +89,10 @@ abstract public class BEASTObject implements BEASTInterface{
     // a method in Object, so it needs to be in BEASTObject
 	@Override
     public String toString() {
-    	return getID();
+		if (getID() != null) {
+			return getID();
+		}
+        return this.getClass().getSimpleName().toLowerCase();
     }
     
     
diff --git a/src/beast/core/Logger.java b/src/beast/core/Logger.java
index 7f04e48..a00fbf8 100644
--- a/src/beast/core/Logger.java
+++ b/src/beast/core/Logger.java
@@ -234,10 +234,14 @@ public class Logger extends BEASTObject {
             for (final Loggable m_logger : loggerList) {
                 m_logger.init(out);
             }
+
+            // Remove trailing tab from header
+            String header = rawbaos.toString().trim();
+
             if (sanitiseHeadersInput.get()) {
-            	m_out.print(sanitiseHeader(rawbaos.toString()));
+            	m_out.print(sanitiseHeader(header));
             } else {
-            	m_out.print(rawbaos.toString());
+            	m_out.print(header);
             }
             
             if ( baos != null ) {
@@ -484,30 +488,31 @@ public class Logger extends BEASTObject {
             }
             sampleNr += sampleOffset;
         }
-        ByteArrayOutputStream baos = null;
-        PrintStream tmp = null;
-        if (m_out == System.out) {
-            tmp = m_out;
-            baos = new ByteArrayOutputStream();
-            m_out = new PrintStream(baos);
-        }
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream out = new PrintStream(baos);
+
         if (mode == LOGMODE.compound) {
-            m_out.print((sampleNr) + "\t");
+            out.print((sampleNr) + "\t");
         }
+
         for (final Loggable m_logger : loggerList) {
-            m_logger.log(sampleNr, m_out);
+            m_logger.log(sampleNr, out);
         }
-        if ( baos != null ) {
-            assert tmp == System.out ;
-
-            m_out = tmp;
-            try {
-                String logContent = baos.toString("ASCII");
-                logContent = prettifyLogLine(logContent);
-                m_out.print(logContent);
-            } catch (UnsupportedEncodingException e) {
-                e.printStackTrace();
-            }
+
+        // Aquire log string and trim excess tab
+        String logContent;
+        try {
+            logContent = baos.toString("ASCII").trim();
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException("ASCII string encoding not supported: required for logging!");
+        }
+
+        // Include calculation speed estimate if this log is going to the terminal
+        if ( m_out == System.out ) {
+            logContent = prettifyLogLine(logContent);
+            m_out.print(logContent);
+
             if (startLogTime < 0) {
                 if (sampleNr - sampleOffset > 6000) {
                     startLogTime++;
@@ -527,8 +532,11 @@ public class Logger extends BEASTObject {
                                 (secondsPerMSamples % 60 + "s");
                 m_out.print(" " + timePerMSamples + "/Msamples");
             }
+            m_out.println();
+
+        } else {
+            m_out.println(logContent);
         }
-        m_out.println();
     } // log
 
 
@@ -593,6 +601,9 @@ public class Logger extends BEASTObject {
         }
     } // close
 
+    public PrintStream getM_out() {
+        return m_out;
+    }
 
     public static int getSampleOffset() {
         return sampleOffset < 0 ? 0 : sampleOffset;
diff --git a/src/beast/core/MCMC.java b/src/beast/core/MCMC.java
index 2406f12..ba6382c 100644
--- a/src/beast/core/MCMC.java
+++ b/src/beast/core/MCMC.java
@@ -119,6 +119,12 @@ public class MCMC extends Runnable {
      */
     protected int storeEvery;
 
+    /**
+     * Set this to true to enable detailed MCMC debugging information
+     * to be displayed.
+     */
+    private static final boolean printDebugInfo = false;
+
     public MCMC() {
     }
 
@@ -384,7 +390,8 @@ public class MCMC extends Runnable {
 //            }
 
             final Operator operator = operatorSchedule.selectOperator();
-            //System.err.print("\n" + sampleNr + " " + operator.getName()+ ":");
+
+            if (printDebugInfo) System.err.print("\n" + sampleNr + " " + operator.getName()+ ":");
 
             final Distribution evaluatorDistribution = operator.getEvaluatorDistribution();
             Evaluator evaluator = null;
@@ -424,7 +431,8 @@ public class MCMC extends Runnable {
                 newLogLikelihood = posterior.calculateLogP();
 
                 logAlpha = newLogLikelihood - oldLogLikelihood + logHastingsRatio; //CHECK HASTINGS
-                // System.err.print(logAlpha + " " + newLogLikelihood + " " + oldLogLikelihood);
+                if (printDebugInfo) System.err.print(logAlpha + " " + newLogLikelihood + " " + oldLogLikelihood);
+
                 if (logAlpha >= 0 || Randomizer.nextDouble() < Math.exp(logAlpha)) {
                     // accept
                     oldLogLikelihood = newLogLikelihood;
@@ -433,7 +441,7 @@ public class MCMC extends Runnable {
                     if (sampleNr >= 0) {
                         operator.accept();
                     }
-                    //System.err.print(" accept");
+                    if (printDebugInfo) System.err.print(" accept");
                 } else {
                     // reject
                     if (sampleNr >= 0) {
@@ -441,7 +449,7 @@ public class MCMC extends Runnable {
                     }
                     state.restore();
                     state.restoreCalculationNodes();
-                    //System.err.print(" reject");
+                    if (printDebugInfo) System.err.print(" reject");
                 }
                 state.setEverythingDirty(false);
             } else {
@@ -454,7 +462,7 @@ public class MCMC extends Runnable {
                     state.setEverythingDirty(false);
                     state.restoreCalculationNodes();
 				}
-				//System.err.print(" direct reject");
+				if (printDebugInfo) System.err.print(" direct reject");
             }
             log(sampleNr);
 
diff --git a/src/beast/evolution/speciation/CalibratedYuleModel.java b/src/beast/evolution/speciation/CalibratedYuleModel.java
index f672d91..7a7ae35 100644
--- a/src/beast/evolution/speciation/CalibratedYuleModel.java
+++ b/src/beast/evolution/speciation/CalibratedYuleModel.java
@@ -38,7 +38,7 @@ import beast.math.statistic.RPNcalculator;
         , DOI = "10.1093/sysbio/syr087", year = 2012, firstAuthorSurname = "heled")
 public class CalibratedYuleModel extends SpeciesTreeDistribution {
 
-    public static enum Type {
+    public enum Type {
         NONE("none"),
         OVER_ALL_TOPOS("full"),
         OVER_RANKED_COUNTS("restricted");
@@ -658,9 +658,13 @@ public class CalibratedYuleModel extends SpeciesTreeDistribution {
         boolean first = true;
 
         int[][] linsInLevels;
-        //int ccc = 0;
+        int ccc = 0;
         while ((linsInLevels = cli.next()) != null) {
-            //ccc++;
+            ccc++;
+            if( ccc > 30000000 ) {
+                issueSlowWarning();
+                //return Double.POSITIVE_INFINITY;
+            }
             double v = countRankedTrees(levels, linsInLevels, joiners, linsAtLevel);
             // 1 for root formula, 1 for kludge in iterator which sets root as 2 lineages
             if (noRoot) {
@@ -717,6 +721,18 @@ public class CalibratedYuleModel extends SpeciesTreeDistribution {
         return val;
     }
 
+    private boolean warningIssued = false;
+    private void issueSlowWarning() {
+        if( ! warningIssued )
+        Log.warning("This calibrated Yule analysis with " + orderedCalibrations.length + " calibrations will take a looong time.\n"
+                +"Possibly will never complete even a single step. You can change the type of the calibration to 'none' (type=\"none\"\n"
+                + "in the XML) and get the non-calibrated Yule just like in BEAST1, or set type to \"restricted\", a variant of the\n" +
+                "calibrated Yule which runs faster and where the proterior distribution of the node times is more similar to the\n" +
+                "actual calibration than the \"none\" case. In both cases test to see how far your posterior calibrations are from the " +
+                "specifications.");
+        warningIssued = true;
+    }
+
     private double
     countRankedTrees(final int levels, final int[][] linsAtCrossings, final int[][] joiners, final int[] linsAtLevel) {
         double logCount = 0;
diff --git a/src/beast/evolution/speciation/SpeciesTreePrior.java b/src/beast/evolution/speciation/SpeciesTreePrior.java
index 80c37c6..cfaf4b5 100644
--- a/src/beast/evolution/speciation/SpeciesTreePrior.java
+++ b/src/beast/evolution/speciation/SpeciesTreePrior.java
@@ -31,7 +31,9 @@ public class SpeciesTreePrior extends TreeDistribution {
     public final Input<RealParameter> popSizesTopInput = new Input<>("topPopSize", "population size parameter at the top of a branch. " +
             "Ignored for constant population function, but required for linear population function.");
 
-    public final Input<RealParameter> gammaParameterInput = new Input<>("gammaParameter", "shape parameter of the gamma distribution", Validate.REQUIRED);
+    public final Input<RealParameter> gammaParameterInput = new Input<>("gammaParameter", "scale parameter of the gamma distribution over population sizes. "
+    		+ "This makes this parameter half the expected population size on all branches for constant population function, "
+    		+ "but a quarter of the expected population size for tip branches only for linear population functions.", Validate.REQUIRED);
 
 //	public Input<RealParameter> m_rootHeightParameter = new Input<>("rootBranchHeight","height of the node above the root, representing the root branch", Validate.REQUIRED);
     /**
diff --git a/src/beast/evolution/substitutionmodel/BinaryCovarion.java b/src/beast/evolution/substitutionmodel/BinaryCovarion.java
index 9abf7fa..683610b 100644
--- a/src/beast/evolution/substitutionmodel/BinaryCovarion.java
+++ b/src/beast/evolution/substitutionmodel/BinaryCovarion.java
@@ -59,7 +59,7 @@ import beast.evolution.datatype.TwoStateCovarion;
  * [    0       ,     s2     ,    p0   , -p0-s2 ]
  *
  * equilibrium frequencies
- * [ f0 * s2/(s1+s2), f1, * s2/(s1+s2), f0 * s1/(s1+s2), f1, * s1/(s1+s2) ]
+ * [ p0 * s2/(s1+s2), p1, * s2/(s1+s2), p0 * s1/(s1+s2), p1, * s1/(s1+s2) ]
  *
  *
  * Note: to use Tuffley & Steel's methods, set a = 0.
@@ -98,6 +98,7 @@ public class BinaryCovarion extends GeneralSubstitutionModel {
         switchRate = switchRateInput.get();
         frequencies = frequenciesInput.get();
         hiddenFrequencies = hfrequenciesInput.get();
+        mode  = modeInput.get();
 
         
         if (mode.equals(MODE.BEAST) || mode.equals(MODE.REVERSIBLE)) {
@@ -128,6 +129,12 @@ public class BinaryCovarion extends GeneralSubstitutionModel {
         	}
         }
 
+        if (!mode.equals(MODE.BEAST)) {
+        	Log.warning.println("If you encounter infinities, or chaing getting stuck, consider using a more robust "
+        			+ "eigen system, by setting the eigenSystem input, e.g. "
+        			+ "eigenSystem=\"beast.evolution.substitutionmodel.RobustEigenSystem\" "
+        			+ "available from the beast-classic package.");
+        }
         
         
         nrOfStates = 4;
@@ -196,8 +203,8 @@ public class BinaryCovarion extends GeneralSubstitutionModel {
 	        freqs[2] = frequencies.getValue(0) * hiddenFrequencies.getValue(1);
 	        freqs[3] = frequencies.getValue(1) * hiddenFrequencies.getValue(1);
         } else {
-        	double h0 = alpha.getValue(1) * (alpha.getValue(0) + alpha.getValue(1));
-        	double h1 = alpha.getValue(0) * (alpha.getValue(0) + alpha.getValue(1));
+        	double h0 = switchRate.getValue(1) / (switchRate.getValue(0) + switchRate.getValue(1));
+        	double h1 = switchRate.getValue(0) / (switchRate.getValue(0) + switchRate.getValue(1));
 	        freqs[0] = frequencies.getValue(0) * h0;
 	        freqs[1] = frequencies.getValue(1) * h0;
 	        freqs[2] = frequencies.getValue(0) * h1;
@@ -252,26 +259,26 @@ public class BinaryCovarion extends GeneralSubstitutionModel {
             assert Math.abs(1.0 - p0 - p1) < 1e-8;
 
             unnormalizedQ[0][1] = a * p1 * f0;
-            unnormalizedQ[0][2] = s * f0;
+            unnormalizedQ[0][2] = s * f1;
             unnormalizedQ[0][3] = 0.0;
 
             unnormalizedQ[1][0] = a * p0 * f0;
             unnormalizedQ[1][2] = 0.0;
-            unnormalizedQ[1][3] = s * f0;
+            unnormalizedQ[1][3] = s * f1;
 
-            unnormalizedQ[2][0] = s * f1;
+            unnormalizedQ[2][0] = s * f0;
             unnormalizedQ[2][1] = 0.0;
             unnormalizedQ[2][3] = p1 * f1;
 
             unnormalizedQ[3][0] = 0.0;
-            unnormalizedQ[3][1] = s * f1;
+            unnormalizedQ[3][1] = s * f0;
             unnormalizedQ[3][2] = p0 * f1;
         }
     	break;
         case TUFFLEYSTEEL: {
             double a = alpha.getValue(0);
             double s1 = switchRate.getValue(0);
-            double s2 = switchRate.getValue(0);
+            double s2 = switchRate.getValue(1);
             double p0 = frequencies.getValue(0);
             double p1 = frequencies.getValue(1);
 
diff --git a/src/beast/evolution/tree/Node.java b/src/beast/evolution/tree/Node.java
index 734e478..b91eda2 100644
--- a/src/beast/evolution/tree/Node.java
+++ b/src/beast/evolution/tree/Node.java
@@ -614,7 +614,7 @@ public class Node extends BEASTObject {
     /**
      * set meta-data according to pattern.
      * Only heights are recognised, but derived classes could deal with
-     * richer meta data pattersn.
+     * richer meta data patterns.
      */
     public void setMetaData(final String pattern, final Object value) {
         startEditing();
diff --git a/src/beast/evolution/tree/RandomTree.java b/src/beast/evolution/tree/RandomTree.java
index 351f82d..61df99e 100644
--- a/src/beast/evolution/tree/RandomTree.java
+++ b/src/beast/evolution/tree/RandomTree.java
@@ -414,6 +414,7 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         if (taxa.size() == 0)
             return;
 
+        String msg = "Failed to generate a random tree (probably a bug).";
         for (int attempts = 0; attempts < 1000; ++attempts) {
             try {
                 nextNodeNr = nrOfTaxa;
@@ -442,18 +443,18 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
                 return;
             } catch (ConstraintViolatedException e) {
                 // need to generate another tree
-            	Log.warning.println("WARNING: Generating a random tree did not succeed. The most common reasons are:");
-            	Log.warning.println("WARNING: 1. there are conflicting monophyletic constraints, for example if both (A,B) "
-            			+ "and (B,C) must be monophyletic no tree will be able to meet these constraints at the same "
-            			+ "time. To fix this, carefully check all clade sets, especially the ones that are expected to "
-            			+ "be nested clades.");
-            	Log.warning.println("WARNING: 2. clade heights are constrained by an upper and lower bound, but the population size "
-            			+ "is too large, so it is very unlikely a generated treed does not violate these constraints. To "
-            			+ "fix this you can try to reduce the popultion size of the population model.");
-            	Log.warning.println("WARNING: Expect BEAST to crash if this is not fixed."); 
+            	msg = "\nWARNING: Generating a random tree did not succeed. The most common reasons are:\n";
+            	msg += "1. there are conflicting monophyletic constraints, for example if both (A,B) \n"
+            			+ "and (B,C) must be monophyletic no tree will be able to meet these constraints at the same \n"
+            			+ "time. To fix this, carefully check all clade sets, especially the ones that are expected to \n"
+            			+ "be nested clades.\n";
+            	msg += "2. clade heights are constrained by an upper and lower bound, but the population size \n"
+            			+ "is too large, so it is very unlikely a generated treed does not violate these constraints. To \n"
+            			+ "fix this you can try to reduce the popultion size of the population model.\n";
+            	msg += "Expect BEAST to crash if this is not fixed.\n"; 
             }
         }
-        throw new RuntimeException("Failed to generate a random tree (probably a bug).");
+        throw new RuntimeException(msg);
     }
     
     /**
diff --git a/src/beast/evolution/tree/Tree.java b/src/beast/evolution/tree/Tree.java
index e137768..ee00c05 100644
--- a/src/beast/evolution/tree/Tree.java
+++ b/src/beast/evolution/tree/Tree.java
@@ -547,6 +547,9 @@ public class Tree extends StateNode implements TreeInterface {
      */
     @Override
     public void assignFromFragile(final StateNode other) {
+        // invalidate cache
+        postCache = null;
+
         final Tree tree = (Tree) other;
         if (m_nodes == null) {
             initArrays();
diff --git a/src/beast/util/AddOnManager.java b/src/beast/util/AddOnManager.java
index 2a3bb99..37e5ac8 100644
--- a/src/beast/util/AddOnManager.java
+++ b/src/beast/util/AddOnManager.java
@@ -152,27 +152,14 @@ public class AddOnManager {
         List<URL> URLs = new ArrayList<>();
         URLs.add(new URL(PACKAGES_XML));
 
-        // check beast.properties file exists in package directory
-        File beastProps = new File(getPackageUserDir() + "/beauti.properties");
-        if (beastProps.exists()) {
-            Properties prop = new Properties();
-
-            try {
-                //load a properties file
-                prop.load(new FileInputStream(beastProps));
-
-                //# url
-                //packages.url=http://...
-                if (prop.containsKey("packages.url")) {
-                    for (String userURLString : prop.getProperty("packages.url").split(",")) {
-                        URLs.add(new URL(userURLString));
-                    }
-                }
-
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
+	    //# url
+	    //packages.url=http://...
+    	String urls = Utils.getBeautiProperty("packages.url");
+    	if (urls != null) {
+	        for (String userURLString : urls.split(",")) {
+	            URLs.add(new URL(userURLString));
+	    	}
+    	}
         return URLs;
     }
     
@@ -183,27 +170,10 @@ public class AddOnManager {
      * package repository and is thus ignored.
      */
     public static void saveRepositoryURLs(List<URL> urls) {
+    	// RRB: if all urls removed, the old urls still pop up when restarting?
         if (urls.size()<1)
             return;
         
-        File propsFile = new File(getPackageUserDir() + "/beauti.properties");
-        Properties prop = new Properties();
-
-        //Load or create properties file
-        if (propsFile.exists()) {
-            try {
-                prop.load(new FileInputStream(propsFile));
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        } else {
-            try {
-                propsFile.createNewFile();
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
-        
         // Modify property
         if (urls.size()>1) {
             StringBuilder sb = new StringBuilder("");
@@ -213,17 +183,9 @@ public class AddOnManager {
                 sb.append(urls.get(i));
             }
             
-            prop.setProperty("packages.url", sb.toString());
+            Utils.saveBeautiProperty("packages.url", sb.toString());
         } else {
-            prop.remove("packages.url");
-        }
-
-        // Write properties file
-        try {
-            prop.store(new FileOutputStream(propsFile),
-                    "Automatically-generated by BEAUti.\n");
-        } catch (IOException ex) {
-            Log.err(ex.getMessage());
+            Utils.saveBeautiProperty("packages.url", null);
         }
     }
 
@@ -877,7 +839,7 @@ public class AddOnManager {
                     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                     Document doc = factory.newDocumentBuilder().parse(versionFile);
                     Element addon = doc.getDocumentElement();
-                    Log.info.println("Loading package " + addon.getAttribute("name") + " v" + addon.getAttribute("version"));
+                    Log.warning.println("Loading package " + addon.getAttribute("name") + " v" + addon.getAttribute("version"));
                 } catch (Exception e) {
                 	// too bad, won't print out any info
                 }
diff --git a/src/beast/util/FrequencySet.java b/src/beast/util/FrequencySet.java
index d79c71b..869d150 100644
--- a/src/beast/util/FrequencySet.java
+++ b/src/beast/util/FrequencySet.java
@@ -82,6 +82,9 @@ public class FrequencySet<T> {
      * get frequency of ith object
      */
     public int getFrequency(int i) {
+        if (!sorted) {
+            sortByFrequency();
+        }
         return getFrequency(sortedList.get(i));
     }
 
diff --git a/src/beast/util/NexusParser.java b/src/beast/util/NexusParser.java
index 39221ef..dbf9a79 100644
--- a/src/beast/util/NexusParser.java
+++ b/src/beast/util/NexusParser.java
@@ -197,7 +197,7 @@ public class NexusParser {
 
     private List<String> getIndexedTranslationMap(final Map<String, String> translationMap, final int origin) {
 
-        Log.info.println("translation map size = " + translationMap.size());
+        Log.warning.println("translation map size = " + translationMap.size());
 
         final String[] taxa = new String[translationMap.size()];
 
diff --git a/src/beast/util/XMLProducer.java b/src/beast/util/XMLProducer.java
index 0429ba9..6af6b7d 100644
--- a/src/beast/util/XMLProducer.java
+++ b/src/beast/util/XMLProducer.java
@@ -836,16 +836,8 @@ public class XMLProducer extends XMLParser {
             // see whether a reasonable id can be generated
             if (beastObject.getID() != null && !beastObject.getID().equals("")) {
                 String id = beastObject.getID();
-                // ensure ID is unique
-                if (IDs.contains(id)) {
-                    int k = 1;
-                    while (IDs.contains(id + k)) {
-                        k++;
-                    }
-                    id = id + k;
-                }
-                buf.append(" id='" + normalise(id) + "'");
-                IDs.add(id);
+                // ensure ID is unique, if not add index behind
+                uniqueID(id, buf);
             }
             isDone.add(beastObject);
         }
@@ -905,6 +897,18 @@ public class XMLProducer extends XMLParser {
         }
     } // pluginToXML
 
+    // ensure ID is unique, if not add index behind
+    private void uniqueID(String id, StringBuffer buf) {
+        if (IDs.contains(id)) {
+            int k = 1;
+            while (IDs.contains(id + k)) {
+                k++;
+            }
+            id = id + k;
+        }
+        buf.append(" id='" + normalise(id) + "'");
+        IDs.add(id);
+    }
 
     /**
      * produce XML for an input of a beast object, both as attribute/value pairs for
diff --git a/src/test/beast/app/tools/LogCombinerTest.java b/src/test/beast/app/tools/LogCombinerTest.java
new file mode 100644
index 0000000..bfd2ca4
--- /dev/null
+++ b/src/test/beast/app/tools/LogCombinerTest.java
@@ -0,0 +1,197 @@
+package test.beast.app.tools;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+
+import beast.app.beauti.BeautiDoc;
+import beast.app.tools.LogCombiner;
+import beast.evolution.tree.Tree;
+import beast.util.LogAnalyser;
+import beast.util.NexusParser;
+import beast.util.Randomizer;
+import junit.framework.TestCase;
+
+public class LogCombinerTest extends TestCase {
+
+	static void creatLogFiles(int filesCount, int sampleInterval, int sampleCount) {
+		for (int i = 0; i < filesCount; i++) {
+			StringBuilder b = new StringBuilder();
+			b.append("Sample\tRandom\n");
+			for (int j = 0; j < sampleCount; j++) {
+				b.append(j * sampleInterval);
+				b.append('\t');
+				b.append(Randomizer.nextDouble());
+				b.append('\n');
+			}
+			try {
+				FileWriter outfile = new FileWriter(new File("tmp_in" + i + ".log"));
+				outfile.write(b.toString());
+				outfile.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	@Test
+	public void testLogCombiner() throws IOException {
+		creatLogFiles(3, 1000, 101);
+		LogAnalyser analyser = new LogAnalyser("tmp_in0.log", 0);
+		assertEquals(101, analyser.getTrace(0).length);
+
+		// combine 3 log files (default burn in 10%)
+		LogCombiner.main(new String[] { "-log", "tmp_in0.log", "tmp_in1.log", "tmp_in2.log", "-o", "tmp_out.log" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		Double[] trace = analyser.getTrace(0);
+		// ensure length of combined trace = 300 - 10% burn in
+		assertEquals(273, trace.length);
+		// ensure last sample nr = 272 x 1000 = 26900
+		assertEquals(272000, trace[trace.length - 1], 1e-10);
+
+		// combine 3 log files with burnin 0
+		LogCombiner.main(new String[] { "-log", "tmp_in0.log", "tmp_in1.log", "tmp_in2.log", "-o", "tmp_out.log",
+				"-burnin", "0" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		assertEquals(303, analyser.getTrace(0).length);
+
+		// test resampling single file
+		LogCombiner.main(
+				new String[] { "-log", "tmp_in0.log", "-o", "tmp_out.log", "-burnin", "0", "-resample", "10000" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		trace = analyser.getTrace(0);
+		// ensure length of combined trace = 10 burn in
+		assertEquals(11, trace.length);
+		// ensure last sample nr = 100000
+		assertEquals(100000, trace[trace.length - 1], 1e-10);
+
+		// test resampling three files
+		LogCombiner.main(new String[] { "-log", "tmp_in0.log", "tmp_in1.log", "tmp_in2.log", "-o", "tmp_out.log",
+				"-burnin", "0", "-resample", "10000" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		trace = analyser.getTrace(0);
+		// ensure length of combined trace = 10 burn in
+		assertEquals(33, trace.length);
+		// ensure last sample nr = 100000
+		assertEquals(320000, trace[trace.length - 1], 1e-10);
+		// new File("tmp_out.log").delete();
+
+		// test renumbering single file
+		LogCombiner.main(new String[] { "-log", "tmp_in0.log", "-o", "tmp_out.log", "-burnin", "0", "-renumber" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		trace = analyser.getTrace(0);
+		// ensure length of combined trace = 300 - 10% burn in
+		assertEquals(101, trace.length);
+		// ensure last sample nr = 101
+		assertEquals(100, trace[trace.length - 1], 1e-10);
+
+		// test renumbering 3 log files
+		LogCombiner.main(new String[] { "-log", "tmp_in0.log", "tmp_in1.log", "tmp_in2.log", "-o", "tmp_out.log",
+				"-burnin", "0", "-renumber" });
+		analyser = new LogAnalyser("tmp_out.log", 0);
+		trace = analyser.getTrace(0);
+		// ensure length of combined trace = 303
+		assertEquals(303, trace.length);
+		// ensure last sample nr = 303
+		assertEquals(302, trace[trace.length - 1], 1e-10);
+	}
+
+	static void creatTreeLogFiles(int filesCount, int sampleInterval, int sampleCount) {
+		for (int i = 0; i < filesCount; i++) {
+			StringBuilder b = new StringBuilder();
+			b.append("#NEXUS\n\n");
+			b.append("Begin taxa;\n");
+			b.append("Dimensions ntax=2;\n");
+			b.append("	                Taxlabels\n");
+			b.append("	                        bonobo \n");
+			b.append("	                        siamang \n");
+			b.append(";\n");
+			b.append("End;\n");
+			b.append("Begin trees;\n");
+			b.append("	        Translate\n");
+			b.append("	                   1 bonobo,\n");
+			b.append("	                   2 siamang\n");
+			b.append(";\n");
+
+			for (int j = 0; j < sampleCount; j++) {
+				b.append("tree STATE_" + j * sampleInterval + " = ");
+				double h = Randomizer.nextDouble();
+				b.append("(1:" + h + ",2:" + h +"):0.0;\n");
+			}
+			b.append("End;\n");
+			try {
+				FileWriter outfile = new FileWriter(new File("tmp_in" + i + ".trees"));
+				outfile.write(b.toString());
+				outfile.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	@Test
+	public void testTreeLogCombiner() throws IOException {
+		creatTreeLogFiles(3, 1000, 101);
+		assertEquals(101, treeCount("tmp_in0.trees"));
+		assertEquals(100000, lastTreeStateNr("tmp_in0.trees"));
+		
+		// combine 3 log files (default burn in 10%)
+		LogCombiner.main(new String[] { "-log", "tmp_in0.trees", "tmp_in1.trees", "tmp_in2.trees", "-o", "tmp_out.trees" });
+		// ensure length of combined trace = 300 - 10% burn in
+		assertEquals(273, treeCount("tmp_out.trees"));
+		// ensure last sample nr = 272 x 1000 = 26900
+		assertEquals(272000, lastTreeStateNr("tmp_out.trees"));
+
+		// combine 3 log files with burnin 0
+		LogCombiner.main(new String[] { "-log", "tmp_in0.trees", "tmp_in1.trees", "tmp_in2.trees", "-o", "tmp_out.trees",
+				"-burnin", "0" });
+		assertEquals(303, treeCount("tmp_out.trees"));
+
+		// test resampling single file
+		LogCombiner.main(
+				new String[] { "-log", "tmp_in0.trees", "-o", "tmp_out.trees", "-burnin", "0", "-resample", "10000" });
+		assertEquals(11, treeCount("tmp_out.trees"));
+		// ensure last sample nr = 100000
+		assertEquals(100000, lastTreeStateNr("tmp_out.trees"));
+
+		// test resampling three files
+		LogCombiner.main(new String[] { "-log", "tmp_in0.trees", "tmp_in1.trees", "tmp_in2.trees", "-o", "tmp_out.trees",
+				"-burnin", "0", "-resample", "10000" });
+		assertEquals(33, treeCount("tmp_out.trees"));
+		// ensure last sample nr = 100000
+		assertEquals(320000, lastTreeStateNr("tmp_out.trees"));
+		// new File("tmp_out.trees").delete();
+
+		// test renumbering single file
+		LogCombiner.main(new String[] { "-log", "tmp_in0.trees", "-o", "tmp_out.trees", "-burnin", "0", "-renumber" });
+		assertEquals(101, treeCount("tmp_out.trees"));
+		// ensure last sample nr = 101
+		assertEquals(100, lastTreeStateNr("tmp_out.trees"));
+
+		// test renumbering 3 log files
+		LogCombiner.main(new String[] { "-log", "tmp_in0.trees", "tmp_in1.trees", "tmp_in2.trees", "-o", "tmp_out.trees",
+				"-burnin", "0", "-renumber" });
+		assertEquals(303, treeCount("tmp_out.trees"));
+		// ensure last sample nr = 303
+		assertEquals(302, lastTreeStateNr("tmp_out.trees"));
+	}
+
+	private int treeCount(String file) throws IOException {
+		NexusParser analyser = new NexusParser();
+		analyser.parseFile(new File(file));
+		return analyser.trees.size();
+	}
+
+	private long lastTreeStateNr(String file) throws IOException {
+		String str = BeautiDoc.load(file);
+		String [] strs = str.split("\n");
+		str = strs[strs.length - 2];
+        String str2 = str.substring(11, str.indexOf("=")).trim();
+        str2 = str2.split("\\s")[0];
+        long logState = Long.parseLong(str2);
+		return logState;
+	}
+}
diff --git a/src/test/beast/core/LoggerTest.java b/src/test/beast/core/LoggerTest.java
new file mode 100644
index 0000000..6478246
--- /dev/null
+++ b/src/test/beast/core/LoggerTest.java
@@ -0,0 +1,129 @@
+package test.beast.core;
+
+import beast.core.Logger;
+import beast.core.parameter.RealParameter;
+import org.junit.*;
+
+import java.io.*;
+import java.util.Random;
+
+import static org.junit.Assert.*;
+
+/**
+ * junit 4
+ * http://www.asjava.com/junit/junit-3-vs-junit-4-comparison/
+ * http://stackoverflow.com/questions/2469911/how-do-i-assert-my-exception-message-with-junit-test-annotation
+ *
+ * @author Walter Xie
+ */
+public class LoggerTest {
+    Logger logger;
+
+    @Before
+    public void setUp() throws Exception {
+        logger = new Logger();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+
+    }
+
+    @Test
+    public void initAndValidate() throws Exception {
+
+    }
+
+    @Test
+    public void isLoggingToStdout() throws Exception {
+        logger = new Logger();
+        logger.initByName("fileName", null, "log", new RealParameter());
+        assertTrue("fileName == null", logger.isLoggingToStdout());
+
+        logger = new Logger();
+        logger.initByName("fileName", "", "log", new RealParameter());
+        assertTrue("fileName.length() == 0", logger.isLoggingToStdout());
+
+        logger = new Logger();
+        logger.initByName("fileName", "beast.log", "log", new RealParameter());
+        assertFalse("fileName = \"beast.log\"", logger.isLoggingToStdout());
+    }
+
+    @Test
+    public void testFileLog() throws Exception {
+        logger = new Logger();
+        logger.initByName("fileName", "beast.log", "log", new RealParameter(new Double[]{0.3, 0.7}));
+        File f_log = new File(logger.fileNameInput.get());
+        if (f_log.exists()) {
+            boolean log_deleted = f_log.delete();
+            System.out.println("Delete log : " + f_log.getAbsolutePath() + " for testFileLog.");
+        }
+
+        logger.init();
+        assertTrue("beast.log created successfully", f_log.exists());
+
+        // rI >= 0
+        int rI = new Random().nextInt(10000000);
+        logger.log(-1);
+        logger.log(rI);
+        logger.close();
+
+        //TODO cannot get "closing" status from PrintStream
+//        assertNull("m_out is beast.log after close", logger.getM_out());
+
+        BufferedReader in = new BufferedReader(new FileReader(f_log));
+        // column names
+        String line = in.readLine();
+        // 1st sample
+        String sample1 = in.readLine();
+        String[] sp = sample1.split("\t", -1);
+        assertFalse("check beast.log -1 not logged", sp[0].equals("-1"));
+        assertEquals("check beast.log 1st sample", Integer.toString(rI), sp[0]);
+    }
+
+    @Test
+    public void testScreenLog() throws Exception {
+        logger = new Logger();
+        logger.initByName("fileName", "", "log", new RealParameter(new Double[]{0.3, 0.7}));
+
+        logger.init();
+        assertTrue("m_out is System.out", logger.getM_out() == System.out);
+
+        logger.log(1);
+        //TODO cannot extract content
+
+        // close all file, except stdout
+        logger.close();
+        assertTrue("m_out is still System.out after close", logger.getM_out() == System.out);
+    }
+
+
+    @Test
+    public void init() throws Exception {
+
+    }
+
+
+    @Test
+    public void log() throws Exception {
+//        logger = new Logger();
+//        logger.initByName("fileName", "", "log", new RealParameter(new Double[]{0.3, 0.7}));
+
+//        logger.log(-1);
+//        assertEquals("", , );
+//        logger.log(1);// need init m_out in openLogFile
+
+
+    }
+
+    @Test
+    public void close() throws Exception {
+
+    }
+
+    @Test
+    public void getSampleOffset() throws Exception {
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/beast/evolution/substmodel/BinaryCovarionModelTest.java b/src/test/beast/evolution/substmodel/BinaryCovarionModelTest.java
new file mode 100644
index 0000000..f289ffc
--- /dev/null
+++ b/src/test/beast/evolution/substmodel/BinaryCovarionModelTest.java
@@ -0,0 +1,125 @@
+package test.beast.evolution.substmodel;
+
+import org.junit.Test;
+
+import beast.core.parameter.RealParameter;
+import beast.evolution.substitutionmodel.BinaryCovarion;
+import beast.evolution.substitutionmodel.Frequencies;
+import beast.util.Randomizer;
+import cern.colt.Arrays;
+import junit.framework.TestCase;
+
+public class BinaryCovarionModelTest extends TestCase {
+    final static double EPSILON = 1e-6;
+
+	
+    /**      
+	 * test that equilibrium frequencies are
+	 * [ p0 * f0, p1, * f0, p0 * f1, p1, * f1 ]
+	 */
+	@Test
+	public void testEquilibriumFrequencies() {
+		Randomizer.setSeed(120);
+		doWithTufflySteel();
+
+		for (int i = 0; i < 10; i++) {
+			doWithEqualHFreqs("BEAST");
+			doWithEqualHFreqs("REVERSIBLE");
+		}
+		doWithUnEqualHFreqs("REVERSIBLE");
+	}
+	
+	private void doWithTufflySteel() {
+	        Frequencies dummyFreqs = new Frequencies();
+	        dummyFreqs.initByName("frequencies", "0.25 0.25 0.25 0.25", "estimate", false);
+	        BinaryCovarion substModel;
+
+	        double d = 0.05+Randomizer.nextDouble()*0.9;
+	        RealParameter vfrequencies = new RealParameter(new Double[]{d, 1.0 - d});
+	        RealParameter switchrate = new RealParameter(new Double[]{Randomizer.nextDouble(), Randomizer.nextDouble()});
+	        
+	        substModel = new BinaryCovarion();
+	        substModel.initByName("frequencies", dummyFreqs, 
+	        		"vfrequencies", vfrequencies, /* [p0, p1] */
+	        		"alpha", "0.01",
+	        		"switchRate", switchrate,
+	        		//"eigenSystem", "beast.evolution.substitutionmodel.RobustEigenSystem",
+	        		"mode", "TUFFLEYSTEEL");
+	        
+	        double [] matrix = new double[16];
+	        substModel.getTransitionProbabilities(null, 1000, 0, 1.0, matrix);
+        	double h0 = switchrate.getValue(1) / (switchrate.getValue(0) + switchrate.getValue(1));
+        	double h1 = switchrate.getValue(0) / (switchrate.getValue(0) + switchrate.getValue(1));
+	        double [] baseFreqs = new double[] {
+	    	        vfrequencies.getValue(0) * h0,
+	    	        vfrequencies.getValue(1) * h0,
+	    	        vfrequencies.getValue(0) * h1,
+	    	        vfrequencies.getValue(1) * h1
+	        };
+	        System.err.println("Expected: " + Arrays.toString(baseFreqs));
+	        System.err.println("Calculat: " + Arrays.toString(matrix));
+	        for (int j = 0; j < 4; j++) {
+	        	assertEquals(baseFreqs[j], matrix[j], 1e-3);
+	        }
+		}
+
+	private void doWithEqualHFreqs(String mode) {
+        Frequencies dummyFreqs = new Frequencies();
+        dummyFreqs.initByName("frequencies", "0.25 0.25 0.25 0.25", "estimate", false);
+        BinaryCovarion substModel;
+
+        RealParameter hfrequencies = new RealParameter(new Double[]{0.5, 0.5});
+        double d = Randomizer.nextDouble();
+        RealParameter vfrequencies = new RealParameter(new Double[]{d, 1.0 - d});
+        
+        substModel = new BinaryCovarion();
+        substModel.initByName("frequencies", dummyFreqs, 
+        		"hfrequencies", hfrequencies, /* [f0, f1] */
+        		"vfrequencies", vfrequencies, /* [p0, p1] */
+        		"alpha", "0.01",
+        		"switchRate", "0.1",
+        		"mode", mode);
+        
+        double [] matrix = new double[16];
+        substModel.getTransitionProbabilities(null, 100, 0, 1.0, matrix);
+        double EPSILON = 1e-10;
+        assertEquals(vfrequencies.getValue(0) * hfrequencies.getValue(0), matrix[0], EPSILON);
+        assertEquals(vfrequencies.getValue(1) * hfrequencies.getValue(0), matrix[1], EPSILON);
+        assertEquals(vfrequencies.getValue(0) * hfrequencies.getValue(1), matrix[2], EPSILON);
+        assertEquals(vfrequencies.getValue(1) * hfrequencies.getValue(1), matrix[3], EPSILON);
+	}
+
+	private void doWithUnEqualHFreqs(String mode) {
+        Frequencies dummyFreqs = new Frequencies();
+        dummyFreqs.initByName("frequencies", "0.25 0.25 0.25 0.25", "estimate", false);
+        BinaryCovarion substModel;
+
+        double d = 0.05+Randomizer.nextDouble()*0.9;
+        RealParameter hfrequencies = new RealParameter(new Double[]{d, 1.0 - d});
+        d = 0.05+Randomizer.nextDouble()*0.9;
+        RealParameter vfrequencies = new RealParameter(new Double[]{d, 1.0 - d});
+        
+        substModel = new BinaryCovarion();
+        substModel.initByName("frequencies", dummyFreqs, 
+        		"hfrequencies", hfrequencies, /* [f0, f1] */
+        		"vfrequencies", vfrequencies, /* [p0, p1] */
+        		"alpha", "0.01",
+        		"switchRate", "0.1",
+        		//"eigenSystem", "beast.evolution.substitutionmodel.RobustEigenSystem",
+        		"mode", mode);
+        
+        double [] matrix = new double[16];
+        substModel.getTransitionProbabilities(null, 1000, 0, 1.0, matrix);
+        double [] baseFreqs = new double[] {
+	        (vfrequencies.getValue(0) * hfrequencies.getValue(0)),
+	        (vfrequencies.getValue(1) * hfrequencies.getValue(0)),
+	        (vfrequencies.getValue(0) * hfrequencies.getValue(1)),
+	        (vfrequencies.getValue(1) * hfrequencies.getValue(1))
+        };
+        System.err.println("Expected: " + Arrays.toString(baseFreqs));
+        System.err.println("Calculat: " + Arrays.toString(matrix));
+        for (int j = 0; j < 4; j++) {
+        	assertEquals(baseFreqs[j], matrix[j], 1e-3);
+        }
+	}
+}
diff --git a/templates/ClockModels.xml b/templates/ClockModels.xml
index 80d1860..bd2e4af 100644
--- a/templates/ClockModels.xml
+++ b/templates/ClockModels.xml
@@ -45,7 +45,7 @@
         <!-- Relaxed clock exponential -->
         <subtemplate id='RelaxedClockExponential' class='beast.evolution.branchratemodel.UCRelaxedClockModel'
                      mainid='ExponentialRelaxedClock.c:$(n)'
-                     suppressInputs='beast.evolution.branchratemodel.UCRelaxedClockModel.distr'>
+                     suppressInputs='beast.evolution.branchratemodel.UCRelaxedClockModel.distr,beast.evolution.branchratemodel.UCRelaxedClockModel.rateQuantiles'>
             <![CDATA[
         <plugin spec='UCRelaxedClockModel' id="ExponentialRelaxedClock.c:$(n)" tree='@Tree.t:$(n)'>
 			<parameter name='clock.rate' id='ucedMean.c:$(n)' value='1.0' estimate='false'/>
@@ -110,7 +110,8 @@
 
         <!-- Relaxed clock log normal -->
         <subtemplate id='RelaxedClockLogNormal' class='beast.evolution.branchratemodel.UCRelaxedClockModel'
-                     mainid='RelaxedClock.c:$(n)'>
+                     mainid='RelaxedClock.c:$(n)'
+                     suppressInputs='beast.evolution.branchratemodel.UCRelaxedClockModel.distr,beast.evolution.branchratemodel.UCRelaxedClockModel.rateQuantiles'>
             <![CDATA[
         <plugin spec='UCRelaxedClockModel' id="RelaxedClock.c:$(n)" tree='@Tree.t:$(n)'>
 			<parameter name='clock.rate' id='ucldMean.c:$(n)' value='1.0'/>
diff --git a/version.xml b/version.xml
index 2a25ca7..912afa0 100644
--- a/version.xml
+++ b/version.xml
@@ -1 +1 @@
-<addon name='BEAST' version='2.4.1' url="https://github.com/CompEvol/beast2/releases/download/2.4.1pre/BEAST.v2.4.1.addon.zip"/>
+<addon name='BEAST' version='2.4.2' url="https://github.com/CompEvol/beast2/releases/download/2.4.2pre/BEAST.v2.4.2.addon.zip"/>

-- 
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