[med-svn] [jmodeltest] 08/14: Imported Upstream version 2.1.10+dfsg

Andreas Tille tille at debian.org
Tue May 10 13:00:05 UTC 2016


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

tille pushed a commit to branch master
in repository jmodeltest.

commit 4cee886fbbaa0098864faf1049d348c64bdf905e
Author: Andreas Tille <tille at debian.org>
Date:   Tue May 10 13:49:41 2016 +0200

    Imported Upstream version 2.1.10+dfsg
---
 Manifest                                           |   2 +-
 README.md                                          |   6 +-
 manual/changelog.tex                               | 141 ++++
 manual/manual.tex                                  | 171 +----
 .../java/es/uvigo/darwin/jmodeltest/ModelTest.java |   6 +-
 .../darwin/jmodeltest/ModelTestConfiguration.java  |  28 +-
 .../jmodeltest/exception/InternalException.java    |   6 +-
 .../jmodeltest/exe/ExternalExecutionManager.java   | 108 ++++
 .../darwin/jmodeltest/exe/MultipleDistributor.java |   3 -
 .../uvigo/darwin/jmodeltest/exe/RunConsense.java   |  20 +-
 .../es/uvigo/darwin/jmodeltest/exe/RunPhyml.java   |   5 +-
 .../darwin/jmodeltest/gui/Frame_Progress.java      |   2 +-
 .../darwin/jmodeltest/io/AlignmentReader.java      |  24 +-
 .../uvigo/darwin/jmodeltest/io/HtmlReporter.java   |  11 +-
 .../es/uvigo/darwin/jmodeltest/io/RFHistogram.java |   4 +-
 .../es/uvigo/darwin/jmodeltest/tree/Consensus.java | 717 +++++++++++++++++++++
 .../darwin/jmodeltest/tree/TreeUtilities.java      | 196 +++++-
 .../uvigo/darwin/jmodeltest/tree/WeightedTree.java |  60 ++
 .../darwin/jmodeltest/utilities/FixedBitSet.java   | 268 ++++++++
 .../jmodeltest/utilities/MyFormattedOutput.java    | 181 ++++++
 src/main/resources/CHANGELOG                       |   6 +
 src/main/resources/README                          |   2 +-
 src/main/resources/resources/template/index.html   |   8 +-
 23 files changed, 1776 insertions(+), 199 deletions(-)

diff --git a/Manifest b/Manifest
index eb461eb..0f84537 100644
--- a/Manifest
+++ b/Manifest
@@ -1,5 +1,5 @@
 Main-Class: es.uvigo.darwin.jmodeltest.ModelTest
-Class-Path: lib/appframework-1.0.3.jar lib/prottest-3.4.1.jar lib/mpj.
+Class-Path: lib/appframework-1.0.3.jar lib/mpj.
  jar lib/pal.jar lib/alter.jar lib/swing-worker-1.1.jar.
  jar lib/freemarker.jar lib/BrowserLauncher2-all-1_3.
  jar lib/jfreechart-1.0.14.jar lib/jcommon-1.0.17.jar
diff --git a/README.md b/README.md
index eaaeb0f..56be2fb 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,16 @@ jModelTest is a tool to carry out statistical selection of best-fit models of nu
 Download
 --------
 
-New distributions of jModelTest will be hosted in google drive: https://drive.google.com/folderview?id=0ByrkKOPtF_n_OUs3d0dNcnJPYXM#list
+Check 'releases' section for the latest distributions.
+
+New revisions of jModelTest will also be hosted in google drive: https://drive.google.com/folderview?id=0ByrkKOPtF_n_OUs3d0dNcnJPYXM#list
 
 --------
 NEWS!
 --------
 
+03/03/2016 - New revision fixed bug with equal taxa name prefixes. Fixed minor bugs.
+
 20/02/2015 - New revision Fixed minor bug in console version. NNI tree search operation was taken as default for ML starting tree, instead of BEST.
 
 20/11/2014 - New revision Fixed some bugs with Windows OS
diff --git a/manual/changelog.tex b/manual/changelog.tex
new file mode 100644
index 0000000..35dd9fd
--- /dev/null
+++ b/manual/changelog.tex
@@ -0,0 +1,141 @@
+\subsection{Last Updates}
+
+\begin{itemize}
+
+  \item 3 Mar 2016 Version 2.1.10 Revision 20160303
+  \begin{itemize}
+    \item Fixed bug with sequences where the 8-char name prefixes are equal
+    \item Added warning when the logging is disabled on runtime
+    \item Added win32 PhyML binary version to compatibility list
+  \end{itemize}
+
+  \item 15 Jan 2016 - Version 2.1.9
+  \begin{itemize}
+    \item Added automatic search for PhyML binary in /usr/bin
+    \item Removed non-ASCII characters
+    \item Disable logging if writing is not possible
+    \item Merge GUI images into jarfile
+  \end{itemize}
+
+  \item 20 Oct 2015 - Version 2.1.8
+  \begin{itemize}
+    \item Removed ReadSeq dependency
+    \item Fixed warnings
+    \item Updated prottest jarfile to v3.4
+  \end{itemize}
+
+
+	\item 20 Feb 2015 - Version 2.1.7
+	\begin{itemize}
+  		\item Fixed bug in ML tree search operation. Console version was using NNI moves instead of "BEST" by default.
+	\end{itemize}
+
+	\item 20 Nov 2014 - Version 2.1.7
+	\begin{itemize}
+		\item Fixed bug with special characters in paths
+		\item Added initial check of PhyML binaries
+		\item Added notification in case AICc produces negative values
+	\end{itemize}
+
+	\item 06 Aug 2014 - Version 2.1.6
+	\begin{itemize}
+		\item Added confirmation window when cancelling running jobs in the GUI
+		\item Added automatic checkpointing files generation
+		\item Added ``-ckp'' argument for loading checkpointing files
+	\end{itemize}
+
+	\item 05 Apr 2014 - Version 2.1.5
+	\begin{itemize}
+		\item Updated OS X binary
+		\item Fixed bug with computation of JC model for ``fixed'' topology
+		\item Fixed bug with DT criterion computation
+		\item Added ``-n'' argument for naming executions (the name is included in the log filenames)
+		\item Added ``-getphylip'' argument for converting alignments into PHYLIP format with ALTER
+		\item Fixed bug in PhyML logging in GUI. Added a unique ID for every model in the log file
+		\item Added PAUP* block into log files if required (``-w'' argument)
+		\item Added more verbose error messages 
+	\end{itemize}
+
+	\item 10 Jul 2013 - Version 2.1.4
+	\begin{itemize}
+		\item Added phyml auto-logging.
+		\item Added phyml command lines for best-fit models.
+		\item Added phyml log tab in the GUI.
+		\item Removed sample size modes (and ``-n'' argument). Sample size is fixed to alignment size.
+		\item Fixed bug with relative paths when calling from a different path.
+		\item Fixed typos in the GUI. 
+	\end{itemize}
+
+	\item 05 Mar 2013 - Version 2.1.3
+	\begin{itemize}
+		\item Fixed bug with PAUP`*` command block.
+		\item Added the possibility to change Inforation Criterion used with the clustering algorithm for the 203 matrices.
+		\item Changed ``-o'' argument for the hypothesis order into ``-O''
+		\item Added ``-o'' argument for forwarding the standard output to a file: -o FILENAME 
+	\end{itemize}
+
+	\item 01 Jan 2013 Version 2.1.2 - Revision 20130103
+	\begin{itemize}
+		\item Fixed bug in paths with whitespaces.
+		\item Updated PhyML binaries. 
+	\end{itemize}
+
+	\item 31 Jul 2012 Version 2.1.1 - Revision 20120731
+	\begin{itemize}
+		\item Fixed bug with hLRT selection when attempting to use a user-defined topology. 
+	\end{itemize}
+
+	\item 11 Mar 2012 Version 2.1 - Revision 20120511
+	\begin{itemize}
+		\item Major updates:
+		\begin{itemize}
+			\item Exhaustive GTR submodels: All the 203 different partitions of the GTR rate matrix can be included in the candidate set of models. When combined with rate variation (+I,+G, +I+G) and equal/unequal base frequencies the total number of possible models is 203 x 8 = 1624. 
+			\item Hill climbing hierarchical clustering: Calculating the likelihood score for a large number of models can be extremely time-consuming. This hill-climbing algorithm implements a hierarchical clustering to search for the best-fit models within the full set of 1624 models, but optimizing at most 288 models while maintaining model selection accuracy. 
+			\item Heuristic filtering: Heuristic reduction of the candidate models set based on a similarity filtering threshold among the GTR rates and the estimates of among-site rate variation. 
+			\item Absolute model fit: Information criterion distances can be calculated for the best-fit model against the unconstrained multinomial model (based on site pattern frequencies). This is computed by default when the alignment does not contain missing data/ambiguities, but can also be approximated otherwise. 
+			\item Topological summary: Tree topologies supported by the different candidate models are summarized in the html log, including confidence intervals constructed from cumulative models weights, plus Robinson-Foulds and Euclidean distances to the best-fit tree for each. 
+		\end{itemize}
+		\item Minor updates:
+		\begin{itemize}
+			\item Corrected a bug in the fixed BIONJ-JC starting topology. F81+I+G was executed instead of JC.
+			\item ``Best'' is now the default tree search operation instead of NNI. ``Best'' computes both NNI and SPR algorithms and selects the best of them.
+			\item User can select the number of threads from GUI. 
+		\end{itemize}
+	\end{itemize}
+
+
+	\item 1 Feb 2012 - Version 2.0.2
+
+	\begin{itemize}
+		\item Added a selection summary at the end of the console output.
+		\item Corrected the table header in the DT results frame (sorting).
+		\item Corrected a bug in DT Criterion where selection could not take place with large alignments.
+		\item Corrected a bug with command console version, where the execution crashed with certain arguments.
+		\item Unified LOCALE for English format. 
+	\end{itemize}
+
+	\item 2 Nov 2011 - Version 2.0.1
+
+	\begin{itemize}
+		\item Improved thread scheduling algorithm.
+		\item OpenMP phyml patch for hybrid execution.
+		\item New argument (machinesfile) for hybrid execution on heterogeneous architectures, or heterogeneous resources distribution. 
+	\end{itemize}
+
+	\item 13 Oct 2011 - Revision 20111013
+
+	\begin{itemize}
+		\item Added conf/jmodeltest.conf file, where you can:
+			Enable/Disable the automatic logging:
+
+			    You might be running a huge dataset and you don't want to generate hundreds or thousands of log files. 
+
+			Set the PhyML binaries location:
+
+			    If you already have installed PhyML in your machine, you can setup jModelTest for use your own binaries. 
+
+		\item Enhanced the html log output. 
+	\end{itemize}
+
+\end{itemize}
+
diff --git a/manual/manual.tex b/manual/manual.tex
index 5adc82f..a05e7fa 100644
--- a/manual/manual.tex
+++ b/manual/manual.tex
@@ -1,4 +1,4 @@
-\documentclass[11pt,twoside,a4paper]{article}
+\documentclass[10pt,twoside,a4paper]{article}
 \usepackage{pslatex,palatino,avant,graphicx}
 \usepackage[usenames,dvipsnames]{color}
 \usepackage[margin=2cm]{geometry}
@@ -46,8 +46,8 @@
 }
 
 \begin{document}
-\providecommand{\versionnumber}{0.1.1}
-\title{jModelTest 2.0 Manual v\versionnumber}
+\providecommand{\versionnumber}{0.1.10}
+\title{jModelTest 2 Manual v\versionnumber}
 \author{Diego Darriba, David Posada}
 \date{\today}
 \maketitle
@@ -55,19 +55,26 @@
 \setcounter{tocdepth}{2}
 \tableofcontents
 
+\clearpage
+
 \section{Overview}
 
 jModelTest is a tool to carry out statistical selection of best-fit models of nucleotide substitution. It implements five different model selection strategies: hierarchical and dynamical likelihood ratio tests (hLRT and dLRT), Akaike and Bayesian information criteria (AIC and BIC), and a decision theory method (DT). It also provides estimates of model selection uncertainty, parameter importances and model-averaged parameter estimates, including model-averaged tree topologies. jModelTest  [...]
 
 \subsection{Download}
 
-The main project webpage is located at google code: \url{http://code.google.com/p/jmodeltest2}.
-
-Google Code downloads are now longer available. New distributions of jModelTest will be hosted in google drive.
+The main project webpage is located at GitHub: \url{https://github.com/ddarriba/jmodeltest2}.
 
-Online help is available at: \url{http://code.google.com/p/jmodeltest2/w/list}.
+New distributions of jModelTest will be hosted in GitHub releases and google drive.
+\begin{itemize}
+  \item \url{https://github.com/ddarriba/jmodeltest2/releases}
+  \item \url{https://drive.google.com/folderview?id=0ByrkKOPtF_n_OUs3d0dNcnJPYXM#list}
+\end{itemize}
 
-Please use the jModelTest discussion group for any question: \url{http://groups.google.com/group/jmodeltest}.
+Please use the jModelTest discussion group for any question: 
+\begin{itemize}
+  \item \url{http://groups.google.com/group/jmodeltest}.
+\end{itemize}
 
 \subsection{Citation}
 
@@ -80,153 +87,17 @@ When using jModelTest you should cite all these:
 
 \subsection{Disclaimer}
 
+{\footnotesize
 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have rec [...]
 
 These programs are protected by their own license and conditions, and using jModelTest implies agreeing with those conditions as well. 
+}
 
-\subsection{Updates}
-
-\begin{itemize}
-
-  \item 15 Jan 2016 - Version 2.1.9
-
-  \begin{itemize}
-    \item Added automatic search for PhyML binary in /usr/bin
-    \item Removed non-ASCII characters
-    \item Disable logging if writing is not possible
-    \item Merge GUI images into jarfile
-  \end{itemize}
-  
-  \item 20 Oct 2015 - Version 2.1.8
-
-  \begin{itemize}
-    \item Removed ReadSeq dependency
-    \item Fixed warnings
-    \item Updated prottest jarfile to v3.4
-  \end{itemize}
-
-	\item 20 Feb 2015 - Version 2.1.7
-
-	\begin{itemize}
-  		\item Fixed bug in ML tree search operation. Console version was using NNI moves instead of "BEST" by default.
-	\end{itemize}
-
-	\item 20 Nov 2014 - Version 2.1.7
-
-	\begin{itemize}
-		\item Fixed bug with special characters in paths
-		\item Added initial check of PhyML binaries
-		\item Added notification in case AICc produces negative values
-	\end{itemize}
-
-	\item 06 Aug 2014 - Version 2.1.6
-
-	\begin{itemize}
-		\item Added confirmation window when cancelling running jobs in the GUI
-		\item Added automatic checkpointing files generation
-		\item Added ``-ckp'' argument for loading checkpointing files
-	\end{itemize}
-
-	\item 05 Apr 2014 - Version 2.1.5
-
-	\begin{itemize}
-		\item Updated OS X binary
-		\item Fixed bug with computation of JC model for ``fixed'' topology
-		\item Fixed bug with DT criterion computation
-		\item Added ``-n'' argument for naming executions (the name is included in the log filenames)
-		\item Added ``-getphylip'' argument for converting alignments into PHYLIP format with ALTER
-		\item Fixed bug in PhyML logging in GUI. Added a unique ID for every model in the log file
-		\item Added PAUP* block into log files if required (``-w'' argument)
-		\item Added more verbose error messages 
-	\end{itemize}
-
-	\item 10 Jul 2013 - Version 2.1.4
-
-	\begin{itemize}
-		\item Added phyml auto-logging.
-		\item Added phyml command lines for best-fit models.
-		\item Added phyml log tab in the GUI.
-		\item Removed sample size modes (and ``-n'' argument). Sample size is fixed to alignment size.
-		\item Fixed bug with relative paths when calling from a different path.
-		\item Fixed typos in the GUI. 
-	\end{itemize}
-
-	\item 05 Mar 2013 - Version 2.1.3
-
-	\begin{itemize}
-		\item Fixed bug with PAUP`*` command block.
-		\item Added the possibility to change Inforation Criterion used with the clustering algorithm for the 203 matrices.
-		\item Changed ``-o'' argument for the hypothesis order into ``-O''
-		\item Added ``-o'' argument for forwarding the standard output to a file: -o FILENAME 
-	\end{itemize}
-
-	\item 01 Jan 2013 Version 2.1.2 - Revision 20130103
-
-	\begin{itemize}
-		\item Fixed bug in paths with whitespaces.
-		\item Updated PhyML binaries. 
-	\end{itemize}
-
-	\item 31 Jul 2012 Version 2.1.1 - Revision 20120731
-
-	\begin{itemize}
-		\item Fixed bug with hLRT selection when attempting to use a user-defined topology. 
-	\end{itemize}
-
-	\item 11 Mar 2012 Version 2.1 - Revision 20120511
-
-	\begin{itemize}
-		\item Major updates:
-		\begin{itemize}
-			\item Exhaustive GTR submodels: All the 203 different partitions of the GTR rate matrix can be included in the candidate set of models. When combined with rate variation (+I,+G, +I+G) and equal/unequal base frequencies the total number of possible models is 203 x 8 = 1624. 
-			\item Hill climbing hierarchical clustering: Calculating the likelihood score for a large number of models can be extremely time-consuming. This hill-climbing algorithm implements a hierarchical clustering to search for the best-fit models within the full set of 1624 models, but optimizing at most 288 models while maintaining model selection accuracy. 
-			\item Heuristic filtering: Heuristic reduction of the candidate models set based on a similarity filtering threshold among the GTR rates and the estimates of among-site rate variation. 
-			\item Absolute model fit: Information criterion distances can be calculated for the best-fit model against the unconstrained multinomial model (based on site pattern frequencies). This is computed by default when the alignment does not contain missing data/ambiguities, but can also be approximated otherwise. 
-			\item Topological summary: Tree topologies supported by the different candidate models are summarized in the html log, including confidence intervals constructed from cumulative models weights, plus Robinson-Foulds and Euclidean distances to the best-fit tree for each. 
-		\end{itemize}
-		\item Minor updates:
-		\begin{itemize}
-			\item Corrected a bug in the fixed BIONJ-JC starting topology. F81+I+G was executed instead of JC.
-			\item ``Best'' is now the default tree search operation instead of NNI. ``Best'' computes both NNI and SPR algorithms and selects the best of them.
-			\item User can select the number of threads from GUI. 
-		\end{itemize}
-	\end{itemize}
-
-
-	\item 1 Feb 2012 - Version 2.0.2
-
-	\begin{itemize}
-		\item Added a selection summary at the end of the console output.
-		\item Corrected the table header in the DT results frame (sorting).
-		\item Corrected a bug in DT Criterion where selection could not take place with large alignments.
-		\item Corrected a bug with command console version, where the execution crashed with certain arguments.
-		\item Unified LOCALE for English format. 
-	\end{itemize}
-
-	\item 2 Nov 2011 - Version 2.0.1
-
-	\begin{itemize}
-		\item Improved thread scheduling algorithm.
-		\item OpenMP phyml patch for hybrid execution.
-		\item New argument (machinesfile) for hybrid execution on heterogeneous architectures, or heterogeneous resources distribution. 
-	\end{itemize}
-
-	\item 13 Oct 2011 - Revision 20111013
-
-	\begin{itemize}
-		\item Added conf/jmodeltest.conf file, where you can:
-			Enable/Disable the automatic logging:
-
-			    You might be running a huge dataset and you don't want to generate hundreds or thousands of log files. 
-
-			Set the PhyML binaries location:
-
-			    If you already have installed PhyML in your machine, you can setup jModelTest for use your own binaries. 
-
-		\item Enhanced the html log output. 
-	\end{itemize}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\end{itemize}
+{\footnotesize
+\include{changelog}
+}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/ModelTest.java b/src/main/java/es/uvigo/darwin/jmodeltest/ModelTest.java
index 5393bf0..42d24b4 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/ModelTest.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/ModelTest.java
@@ -96,10 +96,10 @@ public class ModelTest {
 	public static final double INFINITY = 9999;
 	public static final int MAX_NUM_MODELS = 88;
 	public static final int MAX_NAME = 60;
-	public static final String CURRENT_VERSION = "2.1.9 v20160115";
+	public static final String CURRENT_VERSION = "2.1.10 v20160303";
 	public static final String programName = ("jModeltest");
-	public static final String URL = "http://code.google.com/p/jmodeltest2";
-	public static final String WIKI = "http://code.google.com/p/jmodeltest2/wiki/GettingStarted";
+	public static final String URL = "https://github.com/ddarriba/jmodeltest2";
+	public static final String WIKI = "https://github.com/ddarriba/jmodeltest2";
 	public static final String DISCUSSION_GROUP = "http://groups.google.com/group/jmodeltest";
 	public static String CONFIG_FILE = "conf/jmodeltest.conf";
 	public static final String UNKNOWN_HOSTNAME = "UNKNOWN";
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/ModelTestConfiguration.java b/src/main/java/es/uvigo/darwin/jmodeltest/ModelTestConfiguration.java
index a9b4a66..77031d9 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/ModelTestConfiguration.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/ModelTestConfiguration.java
@@ -28,6 +28,17 @@ import java.util.regex.Pattern;
 
 import es.uvigo.darwin.jmodeltest.utilities.Utilities;
 
+/**
+ * ModelTestConfiguration.java
+ * 
+ * Description: Configuration parameters
+ * 
+ * @author Diego Darriba, University of Vigo / University of A Coruna, Spain
+ *         ddarriba at udc.es
+ * @author David Posada, University of Vigo, Spain dposada at uvigo.es |
+ *         darwin.uvigo.es
+ * @version 2.1.10 (Mar 2016)
+ */
 public abstract class ModelTestConfiguration {
 
 	private static String convertPathToAbsolute(String path) {
@@ -113,7 +124,22 @@ public abstract class ModelTestConfiguration {
             	}
             }
             
-        	if (!existsKey(LOG_DIR)) {
+        	if (existsKey(LOG_DIR)) {
+        		/* test writing */
+        		File logDir = new File(getLogDir());
+        		if ((isCkpEnabled() || isPhymlLogEnabled() || isHtmlLogEnabled()) 
+        				&& !(logDir.exists() && logDir.canWrite()))
+        		{
+        			System.err.println("WARNING: Cannot write in 'log' directory ("
+        					+ getLogDir() + "): All logging will be disabled");
+        			System.err.println("         If you want to fix this warning, check 'conf/jmodeltest.conf'");
+        			System.err.println("         Change the logging directory to where you have writing permission");
+        			System.err.println("         or disable 'checkpointing', 'html-logging' and 'phyml-logging' properties\n");
+        			disableHtmlLog();
+            		disablePhymlLog();
+            		disableCkpLog();
+        		}
+        	} else {
         		disableHtmlLog();
         		disablePhymlLog();
         		disableCkpLog();
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/exception/InternalException.java b/src/main/java/es/uvigo/darwin/jmodeltest/exception/InternalException.java
index 8e9e91d..c50fa08 100755
--- a/src/main/java/es/uvigo/darwin/jmodeltest/exception/InternalException.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/exception/InternalException.java
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 package es.uvigo.darwin.jmodeltest.exception;
 
 /**
- * The Class ProtTestInternalException.
+ * The Class InternalException.
  * 
  * @author Diego Darriba
  */
@@ -28,12 +28,12 @@ public class InternalException extends RuntimeException {
 	private static final long serialVersionUID = 20090728L;
 
 	/**
-	 * Instantiates a new prot test internal exception.
+	 * Instantiates a new internal exception.
 	 */
 	public InternalException() {}
 	
 	/**
-	 * Instantiates a new prot test internal exception.
+	 * Instantiates a new internal exception.
 	 * 
 	 * @param description the description
 	 */
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/exe/ExternalExecutionManager.java b/src/main/java/es/uvigo/darwin/jmodeltest/exe/ExternalExecutionManager.java
new file mode 100644
index 0000000..3ec870e
--- /dev/null
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/exe/ExternalExecutionManager.java
@@ -0,0 +1,108 @@
+/*
+Copyright (C) 2009  Diego Darriba
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package es.uvigo.darwin.jmodeltest.exe;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * A thrid-party applications manager to control proccesses running on
+ * the machine and kill them when necessary.
+ * 
+ * @author Diego Darriba
+ * @since 3.0
+ */
+public class ExternalExecutionManager {
+
+    /** Unique instance of the manager */
+    private static ExternalExecutionManager instance;
+    /** Collection of running processes */
+    private final Collection<Process> processes;
+
+    /**
+     * Instantiates a new execution manager
+     */
+    private ExternalExecutionManager() {
+        this.processes = new ArrayList<Process>();
+    }
+
+    /**
+     * Gets the unique instance of the class
+     * 
+     * @return the ExternalExecutionManager instance
+     */
+    public static ExternalExecutionManager getInstance() {
+        if (instance == null) {
+            instance = new ExternalExecutionManager();
+        }
+        return instance;
+    }
+
+    /**
+     * Adds a process in execution to the collection
+     * 
+     * @param proc the running process
+     * 
+     * @return true, if succesfully added the process
+     */
+    public boolean addProcess(Process proc) {
+        boolean result = false;
+        if (!processes.contains(proc)) {
+            result = processes.add(proc);
+        }
+        return result;
+    }
+
+    /**
+     * Removes a process from the collection
+     * 
+     * @param proc the process to remove
+     * 
+     * @return true, if succesfully removed the process
+     */
+    public boolean removeProcess(Process proc) {
+        boolean result = false;
+        if (processes.contains(proc)) {
+            result = processes.remove(proc);
+        }
+        return result;
+    }
+
+    /**
+     * Kills all running processes in the collection
+     */
+    public void killProcesses() {
+        for (final Process proc : processes) {
+            if (proc != null) {
+                try {
+                    proc.exitValue();
+                } catch (IllegalThreadStateException e) {
+                    // The process is executing, so we should kill it
+                    Runtime.getRuntime().addShutdownHook(
+                            new Thread(new Runnable() {
+
+                        public void run() {
+                            proc.destroy();
+                        }
+                    }));
+                }
+            }
+        }
+        processes.clear();
+    }
+}
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/exe/MultipleDistributor.java b/src/main/java/es/uvigo/darwin/jmodeltest/exe/MultipleDistributor.java
index a6cd081..a587132 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/exe/MultipleDistributor.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/exe/MultipleDistributor.java
@@ -209,8 +209,6 @@ public class MultipleDistributor extends Observable implements Runnable {
 					Thread.sleep(200);
 				} catch (InterruptedException e) {
 					e.printStackTrace();
-					// throw new
-					// ProtTestInternalException("Thread interrupted");
 				}
 
 			}
@@ -228,7 +226,6 @@ public class MultipleDistributor extends Observable implements Runnable {
 				Thread.sleep(200);
 			} catch (InterruptedException e) {
 				e.printStackTrace();
-				// throw new ProtTestInternalException("Thread interrupted");
 			}
 		}
 		caller.rootModel = null;
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunConsense.java b/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunConsense.java
index 0ce334d..8997ba0 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunConsense.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunConsense.java
@@ -17,8 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 package es.uvigo.darwin.jmodeltest.exe;
 
+import java.io.PrintWriter;
 import java.io.PushbackReader;
 import java.io.StringReader;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
@@ -34,12 +36,11 @@ import es.uvigo.darwin.jmodeltest.gui.XManager;
 import es.uvigo.darwin.jmodeltest.io.TextOutputStream;
 import es.uvigo.darwin.jmodeltest.model.Model;
 import es.uvigo.darwin.jmodeltest.selection.InformationCriterion;
+import es.uvigo.darwin.jmodeltest.tree.Consensus;
+import es.uvigo.darwin.jmodeltest.tree.TreeUtilities;
+import es.uvigo.darwin.jmodeltest.tree.WeightedTree;
+import es.uvigo.darwin.jmodeltest.utilities.FixedBitSet;
 import es.uvigo.darwin.jmodeltest.utilities.Utilities;
-import es.uvigo.darwin.prottest.consensus.Consensus;
-import es.uvigo.darwin.prottest.facade.TreeFacade;
-import es.uvigo.darwin.prottest.facade.TreeFacadeImpl;
-import es.uvigo.darwin.prottest.tree.WeightedTree;
-import es.uvigo.darwin.prottest.util.FixedBitSet;
 
 public class RunConsense {
 	
@@ -242,7 +243,6 @@ public class RunConsense {
 	private void printConsensus() {
 		
 		double consensusThreshold = consensusType.equals("50% majority rule")?0.5:1.0;
-		TreeFacade treeFacade = new TreeFacadeImpl();
 		
 		// print results for best AIC model
 		stream.println(" ");stream.println(" ");stream.println(" ");
@@ -306,9 +306,13 @@ public class RunConsense {
         stream.println(" ");
         
         Tree consensusTree = consensus.getConsensusTree();
-        stream.println(treeFacade.toASCII(consensusTree));
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        TreeUtilities.printASCII(consensusTree, pw);
+        pw.flush();
+        stream.println(sw);
         stream.println(" ");
-        String newickTree = treeFacade.toNewick(consensusTree, true, true, true);
+        String newickTree = TreeUtilities.toNewick(consensusTree, true, true, true);
         stream.println(newickTree);
         stream.println(" ");
         stream.println("Note: this tree is unrooted. Branch lengths are the expected number of "
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunPhyml.java b/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunPhyml.java
index 809ef57..073280c 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunPhyml.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/exe/RunPhyml.java
@@ -64,7 +64,10 @@ public abstract class RunPhyml extends Observable implements Observer {
 	protected Model[] models;
 	protected Model gtrModel = null;
 
-	public static final String[] COMPATIBLE_VERSIONS = {"20130103", "20131022", "20141009", "20141029", "20150501"};
+	public static final String[] COMPATIBLE_VERSIONS = {
+		"20130103", "20131022", 
+		"20141009", "20141029", 
+		"20150501", "20151222"};
 	public static String PHYML_VERSION = "3.0";
 
 	public static String PHYML_TREE_SUFFIX = "_phyml_tree_";
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/gui/Frame_Progress.java b/src/main/java/es/uvigo/darwin/jmodeltest/gui/Frame_Progress.java
index 8305ee3..654610b 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/gui/Frame_Progress.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/gui/Frame_Progress.java
@@ -50,12 +50,12 @@ import javax.swing.plaf.BorderUIResource;
 import es.uvigo.darwin.jmodeltest.ApplicationOptions;
 import es.uvigo.darwin.jmodeltest.ModelTest;
 import es.uvigo.darwin.jmodeltest.ModelTestConfiguration;
+import es.uvigo.darwin.jmodeltest.exe.ExternalExecutionManager;
 import es.uvigo.darwin.jmodeltest.exe.ProcessManager;
 import es.uvigo.darwin.jmodeltest.io.TextOutputStream;
 import es.uvigo.darwin.jmodeltest.model.Model;
 import es.uvigo.darwin.jmodeltest.observer.ProgressInfo;
 import es.uvigo.darwin.jmodeltest.utilities.Utilities;
-import es.uvigo.darwin.prottest.exe.ExternalExecutionManager;
 
 public class Frame_Progress extends JModelTestFrame implements Observer,
 		ActionListener {
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/io/AlignmentReader.java b/src/main/java/es/uvigo/darwin/jmodeltest/io/AlignmentReader.java
index f9dc26d..1702fae 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/io/AlignmentReader.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/io/AlignmentReader.java
@@ -33,6 +33,17 @@ import pal.alignment.ReadAlignment;
 import es.uvigo.darwin.jmodeltest.ApplicationOptions;
 import es.uvigo.darwin.jmodeltest.exception.AlignmentParseException;
 
+/**
+ * AlignmentReader.java
+ * 
+ * Description: Class for parsing MSA files
+ * 
+ * @author Diego Darriba, University of Vigo / University of A Coruna, Spain
+ *         ddarriba at udc.es
+ * @author David Posada, University of Vigo, Spain dposada at uvigo.es |
+ *         darwin.uvigo.es
+ * @version 2.1.10 (Mar 2016)
+ */
 public abstract class AlignmentReader {
 	private static ApplicationOptions options = ApplicationOptions
 			.getInstance();;
@@ -107,19 +118,6 @@ public abstract class AlignmentReader {
 		for (int i = 0; i < alignment.getSequenceCount(); i++) {
 			seqNames.add(alignment.getIdentifier(i).getName());
 		}
-
-		String currString;
-		int size = alignment.getSequenceCount();
-		for (int i = 0; i < size; i++) {
-			currString = seqNames.get(i);
-			for (int j = i + 1; j < size; j++) {
-				if (seqNames.get(j).equals(currString)) {
-					throw new AlignmentParseException(
-							"ERROR: There are duplicated taxa names in the alignment: "
-									+ currString);
-				}
-			}
-		}
 		
 		if (debug) {
 			for (int i = 0; i < alignment.getSequenceCount(); i++) {
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/io/HtmlReporter.java b/src/main/java/es/uvigo/darwin/jmodeltest/io/HtmlReporter.java
index 0e4137e..58aa56a 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/io/HtmlReporter.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/io/HtmlReporter.java
@@ -47,8 +47,6 @@ import es.uvigo.darwin.jmodeltest.selection.InformationCriterion;
 import es.uvigo.darwin.jmodeltest.tree.TreeSummary;
 import es.uvigo.darwin.jmodeltest.tree.TreeUtilities;
 import es.uvigo.darwin.jmodeltest.utilities.Utilities;
-import es.uvigo.darwin.prottest.facade.TreeFacade;
-import es.uvigo.darwin.prottest.facade.TreeFacadeImpl;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
 
@@ -60,7 +58,6 @@ public abstract class HtmlReporter {
 			"resources" + File.separator + "homeIcon.gif",
 			"resources" + File.separator + "topIcon.gif",
 			"resources" + File.separator + "logo0.png" };
-	private static TreeFacade treeFacade = new TreeFacadeImpl();
 	private static Map<String, Object> datamodel;
 	private static File LOG_DIR;
 	private static File IMAGES_DIR;
@@ -244,7 +241,7 @@ public abstract class HtmlReporter {
 				ModelTest.getConsensusAIC() != null ? new Integer(1)
 						: new Integer(0));
 		if (ModelTest.getConsensusAIC() != null) {
-			datamodel.put("aicConsensusTree", treeFacade.toNewick(ModelTest
+			datamodel.put("aicConsensusTree", TreeUtilities.toNewick(ModelTest
 					.getConsensusAIC().getConsensus(), true, true, true));
 			datamodel.put("consensusType", ModelTest.getConsensusAIC()
 					.getConsensusType());
@@ -253,7 +250,7 @@ public abstract class HtmlReporter {
 				ModelTest.getConsensusAICc() != null ? new Integer(1)
 						: new Integer(0));
 		if (ModelTest.getConsensusAICc() != null) {
-			datamodel.put("aiccConsensusTree", treeFacade.toNewick(ModelTest
+			datamodel.put("aiccConsensusTree", TreeUtilities.toNewick(ModelTest
 					.getConsensusAICc().getConsensus(), true, true, true));
 			datamodel.put("consensusType", ModelTest.getConsensusAICc()
 					.getConsensusType());
@@ -262,7 +259,7 @@ public abstract class HtmlReporter {
 				ModelTest.getConsensusBIC() != null ? new Integer(1)
 						: new Integer(0));
 		if (ModelTest.getConsensusBIC() != null) {
-			datamodel.put("bicConsensusTree", treeFacade.toNewick(ModelTest
+			datamodel.put("bicConsensusTree", TreeUtilities.toNewick(ModelTest
 					.getConsensusBIC().getConsensus(), true, true, true));
 			datamodel.put("consensusType", ModelTest.getConsensusBIC()
 					.getConsensusType());
@@ -271,7 +268,7 @@ public abstract class HtmlReporter {
 				ModelTest.getConsensusDT() != null ? new Integer(1)
 						: new Integer(0));
 		if (ModelTest.getConsensusDT() != null) {
-			datamodel.put("dtConsensusTree", treeFacade.toNewick(ModelTest
+			datamodel.put("dtConsensusTree", TreeUtilities.toNewick(ModelTest
 					.getConsensusDT().getConsensus(), true, true, true));
 			datamodel.put("consensusType", ModelTest.getConsensusDT()
 					.getConsensusType());
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/io/RFHistogram.java b/src/main/java/es/uvigo/darwin/jmodeltest/io/RFHistogram.java
index a2970f4..6bc9330 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/io/RFHistogram.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/io/RFHistogram.java
@@ -54,12 +54,14 @@ public class RFHistogram {
 		List<Model> models = ic.getConfidenceModels();
 		
 		Tree bestTree = ic.getMinModel().getTree();
+		int maxRF = 2 * (bestTree.getIdCount()-3);
 		double values[] = new double[models.size()-1];
 		int i = 0;
 		for (Model model : models) {
 			if (!model.equals(ic.getMinModel())) {
 				double distance = distances.getDistance(bestTree, model.getTree());
-				values[i] = distance;
+				/* make relative RF distance */
+				values[i] = 1.0 * distance / maxRF;
 				i++;
 			}
 		}
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/tree/Consensus.java b/src/main/java/es/uvigo/darwin/jmodeltest/tree/Consensus.java
new file mode 100644
index 0000000..d20134e
--- /dev/null
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/tree/Consensus.java
@@ -0,0 +1,717 @@
+/*
+Copyright (C) 2009  Diego Darriba
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package es.uvigo.darwin.jmodeltest.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Set;
+
+import pal.misc.IdGroup;
+import pal.tree.Node;
+import pal.tree.NodeFactory;
+import pal.tree.SimpleTree;
+import pal.tree.Tree;
+import es.uvigo.darwin.jmodeltest.exception.InternalException;
+import es.uvigo.darwin.jmodeltest.model.Model;
+import es.uvigo.darwin.jmodeltest.selection.InformationCriterion;
+import es.uvigo.darwin.jmodeltest.utilities.FixedBitSet;
+import es.uvigo.darwin.jmodeltest.utilities.MyFormattedOutput;
+import es.uvigo.darwin.jmodeltest.utilities.Utilities;
+
+/**
+ * Phylogenetic consensus tree builder.
+ * 
+ * @author Diego Darriba
+ * @since 3.0
+ */
+public class Consensus {
+
+    /** Display branch suport as percent. */
+    final static public boolean SUPPORT_AS_PERCENT = false;
+    /** Calculate branch lengths as weighted average. */
+    final static public int BRANCH_LENGTHS_AVERAGE = 1;
+    /** Calculate branch lengths as weighted median. */
+    final static public int BRANCH_LENGTHS_MEDIAN = 2;
+    /** Default branch lengths algorithm */
+    private static final BranchDistances DEFAULT_BRANCH_DISTANCES =
+            BranchDistances.WeightedMedian;
+    /** The Constant FIRST (just for source code visibility). */
+    private static final int FIRST = 0;
+    /** The weighted trees in consensus. */
+    private List<WeightedTree> trees;
+    /** The cummulative weight. */
+    private double cumWeight = 0.0;
+    /** The number of taxa. */
+    private int numTaxa;
+    /** The common id group of the tree set. */
+    private IdGroup idGroup;
+    /** The set of clade supports. */
+    private Map<FixedBitSet, Support> support =
+            new HashMap<FixedBitSet, Support>();
+    /** The set of clade supports to get from outside this class. */
+    private Map<FixedBitSet, Double> cladeSupport;
+    /** The inner consensus tree. */
+    private Tree consensusTree;
+    /** The splits included in consensus tree */
+    private List<FixedBitSet> splitsInConsensus = new ArrayList<FixedBitSet>();
+    /** The splits not included in consensus tree */
+    private List<FixedBitSet> splitsOutFromConsensus = new ArrayList<FixedBitSet>();
+
+    /**
+     * Gets the clade support, with Support instances
+     * 
+     * @return the map of the support for each bitSet
+     */
+    private Map<FixedBitSet, Support> getSupport() {
+        return support;
+    }
+
+    /**
+     * Gets the double precision clade support
+     * 
+     * @return the map of the support for each bitSet
+     */
+    public Map<FixedBitSet, Double> getCladeSupport() {
+
+        if (cladeSupport == null) {
+            cladeSupport = new HashMap<FixedBitSet, Double>(support.size());
+            FixedBitSet[] keys = support.keySet().toArray(new FixedBitSet[0]);
+            Arrays.sort(keys);
+
+            for (FixedBitSet fbs : keys) {
+                cladeSupport.put(fbs, support.get(fbs).treesWeightWithClade / cumWeight);
+            }
+        }
+        return cladeSupport;
+    }
+
+    /**
+     * Gets the Id Group of the set of trees
+     * 
+     * @return the id group
+     */
+    public IdGroup getIdGroup() {
+        return idGroup;
+    }
+
+    /**
+     * Gets the consensus tree
+     * 
+     * @return the consensus tree
+     */
+    public Tree getConsensusTree() {
+        return consensusTree;
+    }
+
+    /**
+     * Gets the set of trees included in the consensus.
+     * 
+     * @return the trees
+     */
+    public Collection<WeightedTree> getTrees() {
+        return trees;
+    }
+
+    /**
+     * Adds a weighted tree to the set.
+     * 
+     * @param wTree the weighted tree
+     * 
+     * @return true, if successful
+     */
+    private boolean addTree(WeightedTree wTree) {
+        //check integrity
+        if (wTree.getTree() == null || wTree.getWeight() < 0.0) {
+            throw new InternalException();
+        }
+        //check compatibility
+        if (trees.isEmpty()) {
+            trees.add(wTree);
+            numTaxa = wTree.getTree().getIdCount();
+            idGroup = pal.tree.TreeUtils.getLeafIdGroup(wTree.getTree());
+        } else {
+            if (wTree.getTree().getIdCount() != numTaxa) {
+                return false;
+            }
+            Tree pTree = trees.get(FIRST).getTree();
+            for (int i = 0; i < numTaxa; i++) {
+                boolean found = false;
+                for (int j = 0; j < numTaxa; j++) {
+                    if (wTree.getTree().getIdentifier(i).equals(pTree.getIdentifier(j))) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    System.out.println("NOT COMPATIBLE TREES");
+                    return false;
+                }
+            }
+            trees.add(wTree);
+        }
+        cumWeight += wTree.getWeight();
+        return true;
+    }
+
+    /**
+     * Instantiates a new consensus tree builder.
+     * 
+     * @param ic the information criterion to build the weighted trees
+     * @param supportThreshold the minimum support for a clade
+     */
+    public Consensus(InformationCriterion ic, double supportThreshold) {
+        this(ic, supportThreshold, 0);
+    }
+
+    /**
+     * Instantiates a new consensus tree builder.
+     * 
+     * @param ic the information criterion to build the weighted trees
+     * @param supportThreshold the minimum support for a clade
+     * @param branchDistances the method to get the consensus branch lengths
+     */
+    public Consensus(InformationCriterion ic, double supportThreshold, int branchDistances) {
+        this.trees = new ArrayList<WeightedTree>();
+        for (Model model : ic.getConfidenceModels()) {
+        	WeightedTree wTree = new WeightedTree(
+                                       model.getTree(),
+                                       ic.getWeight(model));
+            this.addTree(wTree);
+        }
+        consensusTree = buildTree(supportThreshold, getBranchDistances(branchDistances));
+    }
+
+    /**
+     * Instantiates a new unweighted consensus builder.
+     *
+     * @param trees the trees
+     * @param supportThreshold the minimum support for a clade
+     * @param branchDistances the method to get the consensus branch lengths
+     */
+    public Consensus(List<WeightedTree> trees, double supportThreshold, int branchDistances) {
+        this.trees = new ArrayList<WeightedTree>();
+        for (WeightedTree tree : trees) {
+            this.addTree(tree);
+        }
+
+        consensusTree = buildTree(supportThreshold, getBranchDistances(branchDistances));
+    }
+
+    /**
+     * Calculates rooted support.
+     * 
+     * @param wTree the weighted tree instance
+     * @param node the node
+     * @param support the support
+     * 
+     * @return the fixed bit set
+     */
+    private FixedBitSet rootedSupport(WeightedTree wTree, Node node, Map<FixedBitSet, Support> support) {
+        FixedBitSet clade = new FixedBitSet(numTaxa);
+        if (node.isLeaf()) {
+            clade.set(idGroup.whichIdNumber(node.getIdentifier().getName()));
+        } else {
+            for (int i = 0; i < node.getChildCount(); i++) {
+                Node n = node.getChild(i);
+                FixedBitSet childClade = rootedSupport(wTree, n, support);
+                clade.union(childClade);
+            }
+        }
+
+        Support s = support.get(clade);
+        if (s == null) {
+            s = new Support();
+            support.put(clade, s);
+        }
+        s.add(wTree.getWeight(), TreeUtilities.safeNodeHeight(wTree.getTree(), node), node.getBranchLength());
+        return clade;
+    }
+
+    /**
+     * Detach the children of a tree.
+     * 
+     * @param tree the tree
+     * @param node the node to detach
+     * @param split the split
+     * 
+     * @return the node
+     */
+    public Node detachChildren(Tree tree, Node node, List<Integer> split) {
+        assert (split.size() > 1);
+
+        List<Node> detached = new ArrayList<Node>();
+
+        for (int n : split) {
+            detached.add(node.getChild(n));
+        }
+
+        Node saveRoot = tree.getRoot();
+
+        List<Integer> toRemove = new ArrayList<Integer>();
+        for (int i = 0; i < node.getChildCount(); i++) {
+            Node n = node.getChild(i);
+            if (detached.contains(n)) {
+                toRemove.add(0, i);
+            }
+        }
+        for (int i : toRemove) {
+            node.removeChild(i);
+        }
+
+        Node dnode = NodeFactory.createNode(detached.toArray(new Node[0]));
+        node.addChild(dnode);
+
+        tree.setRoot(saveRoot);
+
+        return dnode;
+    }
+
+    /**
+     * Builds the consensus tree over a set of weighted trees.
+     * 
+     * @param supportThreshold the minimum support to consider a split into the consensus tree
+     * 
+     * @return the consensus tree
+     */
+    private Tree buildTree(double supportThreshold, BranchDistances branchDistances) {
+
+        if (trees.isEmpty()) {
+            throw new InternalException("There are no trees to consense");
+        }
+
+        if (supportThreshold < 0.5 || supportThreshold > 1.0) {
+            throw new InternalException("Invalid threshold value: " + supportThreshold);
+        }
+        
+        double effectiveThreshold = supportThreshold;
+        if (supportThreshold == 0.5) {
+            effectiveThreshold += 1.0/(numTaxa+1);
+        } else if (supportThreshold == 1.0) {
+            effectiveThreshold -= 1.0/(numTaxa+1);
+        }
+
+        // establish support
+        support = new HashMap<FixedBitSet, Support>();
+        for (WeightedTree wTree : trees) {
+            rootedSupport(wTree, wTree.getTree().getRoot(), support);
+        }
+
+        Tree cons = new SimpleTree();
+
+        // Contains all internal nodes in the tree so far, ordered so descendants
+        // appear later than ancestors
+        List<Node> internalNodes = new ArrayList<Node>(numTaxa);
+
+        // For each internal node, a bit-set with the complete set of tips for it's clade
+        List<FixedBitSet> internalNodesTips = new ArrayList<FixedBitSet>(numTaxa);
+        assert idGroup.getIdCount() == numTaxa;
+
+        // establish a tree with one root having all tips as descendants
+        internalNodesTips.add(new FixedBitSet(numTaxa));
+        FixedBitSet rooNode = internalNodesTips.get(0);
+        Node[] nodes = new Node[numTaxa];
+        for (int nt = 0; nt < numTaxa; ++nt) {
+            nodes[nt] = NodeFactory.createNode(idGroup.getIdentifier(nt));
+            rooNode.set(nt);
+        }
+
+        Node rootNode = NodeFactory.createNode(nodes);
+        internalNodes.add(rootNode);
+        cons.setRoot(rootNode);
+        // sorts support from largest to smallest
+        final Comparator<Map.Entry<FixedBitSet, Support>> comparator = new Comparator<Map.Entry<FixedBitSet, Support>>() {
+
+            @Override
+            public int compare(Map.Entry<FixedBitSet, Support> o1, Map.Entry<FixedBitSet, Support> o2) {
+                double diff = o2.getValue().treesWeightWithClade - o1.getValue().treesWeightWithClade;
+                if (diff > 0.0) {
+                    return 1;
+                } else if (diff < 0.0) {
+                    return -1;
+                } else {
+                    return 0;
+                }
+            }
+        };
+
+        // add everything to queue
+        PriorityQueue<Map.Entry<FixedBitSet, Support>> queue =
+                new PriorityQueue<Map.Entry<FixedBitSet, Support>>(support.size(), comparator);
+
+        for (Map.Entry<FixedBitSet, Support> se : support.entrySet()) {
+            Support s = se.getValue();
+            FixedBitSet clade = se.getKey();
+            final int cladeSize = clade.cardinality();
+            if (cladeSize == numTaxa) {
+                // root
+                cons.getRoot().setNodeHeight(s.sumBranches / trees.size());
+                cons.getRoot().setBranchLength(branchDistances.build(s.branchLengths));
+                continue;
+            }
+
+            if (Math.abs(s.treesWeightWithClade - this.cumWeight) < 1e-5 && cladeSize == 1) {
+                // leaf/external node
+                final int nt = clade.nextOnBit(FIRST);
+                final Node leaf = cons.getExternalNode(nt);
+                leaf.setNodeHeight(s.sumBranches / trees.size());
+                leaf.setBranchLength(branchDistances.build(s.branchLengths));
+            } else {
+                queue.add(se);
+            }
+        }
+
+        while (queue.peek() != null) {
+            Map.Entry<FixedBitSet, Support> e = queue.poll();
+            final Support s = e.getValue();
+
+            final double psupport = (1.0 * s.treesWeightWithClade) / cumWeight;
+            if (psupport < effectiveThreshold) {
+                break;
+            }
+
+            final FixedBitSet cladeTips = e.getKey();
+
+            boolean found = false;
+
+            /* locate the node containing the clade. going in reverse order 
+            ensures the lowest one is hit first */
+            for (int nsub = internalNodesTips.size() - 1; nsub >= 0; --nsub) {
+
+                FixedBitSet allNodeTips = internalNodesTips.get(nsub);
+
+                // size of intersection between tips & split
+                final int nSplit = allNodeTips.intersectCardinality(cladeTips);
+
+                if (nSplit == cladeTips.cardinality()) {
+                    // node contains all of clade
+
+                    // Locate node descendants containing the split
+                    found = true;
+                    List<Integer> split = new ArrayList<Integer>();
+
+                    Node n = internalNodes.get(nsub);
+                    int l = 0;
+
+                    for (int j = 0; j < n.getChildCount(); j++) {
+                        Node ch = n.getChild(j);
+
+                        if (ch.isLeaf()) {
+                            if (cladeTips.contains(idGroup.whichIdNumber(ch.getIdentifier().getName()))) {
+                                split.add(l);
+                            }
+                        } else {
+                            // internal
+                            final int o = internalNodes.indexOf(ch);
+                            final int i = internalNodesTips.get(o).intersectCardinality(cladeTips);
+                            if (i == internalNodesTips.get(o).cardinality()) {
+                                split.add(l);
+                            } else if (i > 0) {
+                                // Non compatible
+                                found = false;
+                                break;
+                            }
+                        }
+                        ++l;
+                    }
+
+
+                    if (!(found && split.size() < n.getChildCount())) {
+                        found = false;
+                        break;
+                    }
+
+                    if (split.isEmpty()) {
+                        System.err.println("Bug??");
+                        assert (false);
+                    }
+
+                    final Node detached = detachChildren(cons, n, split);
+
+                    final double height = s.sumBranches / s.nTreesWithClade;
+                    detached.setNodeHeight(height);
+                    detached.setBranchLength(branchDistances.build(s.branchLengths));
+
+                    cons.setAttribute(detached, TreeUtilities.TREE_CLADE_SUPPORT_ATTRIBUTE, SUPPORT_AS_PERCENT ? 100 * psupport : psupport);
+
+                    // insert just after parent, so before any descendants
+                    internalNodes.add(nsub + 1, detached);
+                    internalNodesTips.add(nsub + 1, new FixedBitSet(cladeTips));
+
+                    break;
+                }
+            }
+        }
+
+        TreeUtilities.insureConsistency(cons, cons.getRoot());
+
+        String thresholdAsPercent = String.valueOf(supportThreshold * 100);
+        cons.setAttribute(cons.getRoot(), TreeUtilities.TREE_NAME_ATTRIBUTE,
+                "cons_" + thresholdAsPercent + "_majRule");
+
+        Set<FixedBitSet> keySet = getSupport().keySet();
+        FixedBitSet[] keys = keySet.toArray(new FixedBitSet[0]);
+        Arrays.sort(keys);
+
+        for (FixedBitSet fbs : keys) {
+            if (fbs.cardinality() > 1) {
+                double psupport = (1.0 * getSupport().get(fbs).getTreesWeightWithClade()) / cumWeight;
+                if (psupport < effectiveThreshold) {
+                    splitsOutFromConsensus.add(fbs);
+                } else {
+                    splitsInConsensus.add(fbs);
+                }
+            }
+        }
+
+        return cons;
+
+    }
+
+    /**
+     * Enum to calculate the branch lengths
+     */
+    private enum BranchDistances {
+
+        WeightedAverage {
+
+            /**
+             * Calculates the weighted average.
+             * 
+             * @param values the weighted values
+             * @param cumWeight the sum of weights
+             * 
+             * @return the weighted average of the set
+             */
+            @Override
+            public double build(List<WeightLengthPair> values) {
+                double avg = 0.0;
+                double cumWeight = 0.0;
+                for (WeightLengthPair pair : values) {
+                    avg += pair.branchLength * pair.weight;
+                    cumWeight += pair.weight;
+                }
+                avg /= cumWeight;
+                return avg;
+            }
+        },
+        WeightedMedian {
+
+            /**
+             * Calculates the weighted median.
+             * 
+             * @param values the weighted values
+             * @param cumWeight the sum of weights
+             * 
+             * @return the weighted median of the set
+             */
+            @Override
+            public double build(List<WeightLengthPair> values) {
+                Collections.sort(values);
+                double median = -1;
+                double cumWeight = 0.0;
+                for (WeightLengthPair pair : values) {
+                    cumWeight += pair.weight;
+                }
+                double halfWeight = cumWeight / 2.0;
+                double cumValue = 0.0;
+                for (WeightLengthPair pair : values) {
+                    cumValue += pair.weight;
+                    if (cumValue >= halfWeight) {
+                        median = pair.branchLength;
+                        break;
+                    }
+                }
+                return median;
+            }
+        };
+
+        public abstract double build(List<WeightLengthPair> values);
+    }
+
+    /**
+     * One clade support.
+     */
+    static final class Support {
+
+        /** number of trees containing the clade. */
+        private int nTreesWithClade;
+        /** The trees weight with clade. */
+        private double treesWeightWithClade;
+        /** The branch lengths. */
+        private ArrayList<WeightLengthPair> branchLengths;
+        /** Sum of node heights of trees containing the clade. */
+        private double sumBranches;
+
+        public double getTreesWeightWithClade() {
+            return treesWeightWithClade;
+        }
+
+        /**
+         * Instantiates a new support.
+         */
+        Support() {
+            sumBranches = 0.0;
+            treesWeightWithClade = 0.0;
+            nTreesWithClade = 0;
+            branchLengths = new ArrayList<WeightLengthPair>();
+        }
+
+        /**
+         * Adds the branch to the map of branch lengths.
+         * 
+         * @param weight the weight
+         * @param height the height
+         * @param branchLength the branch length
+         */
+        public final void add(double weight, double height, double branchLength) {
+            sumBranches += height;
+            branchLengths.add(new WeightLengthPair(weight, branchLength));
+            treesWeightWithClade += weight;
+            ++nTreesWithClade;
+
+//            double testW = 0.0;
+//            for (WeightLengthPair wlp : branchLengths) {
+//                testW += wlp.weight;
+//            }
+        }
+    }
+
+    static class WeightLengthPair implements Comparable<WeightLengthPair> {
+
+        private double weight;
+        private double branchLength;
+
+        WeightLengthPair(double weight, double branchLength) {
+            this.weight = weight;
+            this.branchLength = branchLength;
+        }
+
+        @Override
+        public int compareTo(WeightLengthPair o) {
+            if (branchLength < o.branchLength) {
+                return -1;
+            } else if (branchLength > o.branchLength) {
+                return 1;
+            }
+            return 0;
+        }
+    }
+
+    /**
+     * A extension of Weighted tree but every tree
+     * has the same weight.
+     */
+    static class UnweightedTree extends WeightedTree {
+
+        /**
+         * Instantiates a new unweighted tree.
+         * 
+         * @param tree the tree
+         */
+        UnweightedTree(Tree tree) {
+            super(tree, 1.0);
+        }
+    }
+
+    public String getTaxaHeader() {
+        StringBuilder taxaHeader = new StringBuilder();
+        for (int i = 0; i < numTaxa; i++) {
+            taxaHeader.append(String.valueOf(i + 1).charAt(0));
+        }
+        if (numTaxa >= 10) {
+            taxaHeader.append('\n');
+            taxaHeader.append(MyFormattedOutput.space(4 + 9, ' '));
+            for (int i = 9; i < numTaxa; i++) {
+                taxaHeader.append(String.valueOf(i + 1).charAt(1));
+            }
+        }
+        if (numTaxa >= 100) {
+            taxaHeader.append('\n');
+            taxaHeader.append(MyFormattedOutput.space(4 + 99, ' '));
+            for (int i = 99; i < numTaxa; i++) {
+                taxaHeader.append(String.valueOf(i + 1).charAt(2));
+            }
+        }
+        if (numTaxa >= 1000) {
+            taxaHeader.append('\n');
+            taxaHeader.append(MyFormattedOutput.space(4 + 999, ' '));
+            for (int i = 999; i < numTaxa; i++) {
+                taxaHeader.append(String.valueOf(i + 1).charAt(3));
+            }
+        }
+
+        return taxaHeader.toString();
+    }
+
+    public String getSetsIncluded() {
+        StringBuilder setsIncluded = new StringBuilder();
+        setsIncluded.append("    ");
+        setsIncluded.append(getTaxaHeader());
+
+        setsIncluded.append('\n');
+        for (FixedBitSet fbs : splitsInConsensus) {
+            setsIncluded.append("    ")
+                    .append(fbs.splitRepresentation())
+                    .append(" ( ")
+                    .append(Utilities.roundDoubleTo(getCladeSupport().get(fbs), 5))
+                    .append(" )")
+                    .append('\n');
+        }
+        return setsIncluded.toString();
+    }
+
+    public String getSetsNotIncluded() {
+        StringBuilder setsIncluded = new StringBuilder();
+        setsIncluded.append("    ");
+        setsIncluded.append(getTaxaHeader());
+
+        setsIncluded.append('\n');
+        for (FixedBitSet fbs : splitsOutFromConsensus) {
+            setsIncluded.append("    ")
+                    .append(fbs.splitRepresentation())
+                    .append(" ( ")
+                    .append(Utilities.roundDoubleTo(getCladeSupport().get(fbs), 5))
+                    .append(" )")
+                    .append('\n');
+        }
+        return setsIncluded.toString();
+    }
+
+    private BranchDistances getBranchDistances(int value) {
+        BranchDistances bd;
+        switch (value) {
+            case BRANCH_LENGTHS_AVERAGE:
+                bd = BranchDistances.WeightedAverage;
+                break;
+            case BRANCH_LENGTHS_MEDIAN:
+                bd = BranchDistances.WeightedMedian;
+                break;
+            default:
+                // Weighted average
+                bd = DEFAULT_BRANCH_DISTANCES;
+        }
+        return bd;
+    }
+}
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/tree/TreeUtilities.java b/src/main/java/es/uvigo/darwin/jmodeltest/tree/TreeUtilities.java
index 7b54e98..e0f5f8b 100644
--- a/src/main/java/es/uvigo/darwin/jmodeltest/tree/TreeUtilities.java
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/tree/TreeUtilities.java
@@ -23,7 +23,9 @@ import java.io.StringWriter;
 
 import pal.io.FormattedOutput;
 import pal.misc.IdGroup;
+import pal.misc.Identifier;
 import pal.tree.Node;
+import pal.tree.NodeUtils;
 import pal.tree.ReadTree;
 import pal.tree.SplitSystem;
 import pal.tree.SplitUtils;
@@ -32,7 +34,10 @@ import pal.tree.TreeParseException;
 
 public class TreeUtilities {
 
-	public static final String TREE_CLADE_SUPPORT_ATTRIBUTE = "support";
+    public static final int DEFAULT_COLUMN_WIDTH = 70;
+    public static final String TREE_WEIGHT_ATTRIBUTE = "weight";
+    public static final String TREE_CLADE_SUPPORT_ATTRIBUTE = "support";
+    public static final String TREE_NAME_ATTRIBUTE = "treeName";
 
 	public TreeUtilities() {
 	}
@@ -60,6 +65,195 @@ public class TreeUtilities {
 		return tree;
 	}
 
+	/**
+     * Make sure subtree below node has consistent heights, i.e. node height is higher than it's descendants
+     * 
+     * @param tree the tree
+     * @param node the node
+     * 
+     * @return height of node
+     */
+    public static double insureConsistency(Tree tree, Node node) {
+        double height = TreeUtilities.safeNodeHeight(tree, node);
+        if (node.isLeaf()) {
+            return height;
+        } else {
+            for (int i = 0; i < node.getChildCount(); i++) {
+                Node n = node.getChild(i);
+                final double childHeight = insureConsistency(tree, n);
+                height = Math.max(height, childHeight);
+            }
+        }
+
+        node.setNodeHeight(height);
+        return height;
+    }
+    
+    /**
+     * Calculates the number of branches from node to most remote tip.
+     * 
+     * @param node the starting node
+     * 
+     * @return the node distance
+     */
+    public static int nodeDistance(final Node node) {
+        if (node.isLeaf()) {
+            return 0;
+        }
+
+        int d = 0;
+        for (int i = 0; i < node.getChildCount(); i++) {
+            Node n = node.getChild(i);
+            d = Math.max(d, nodeDistance(n));
+        }
+        return d + 1;
+    }
+    /**
+     * Calculates the safe node height.
+     * 
+     * @param tree the tree
+     * @param node the node
+     * 
+     * @return the height of the node
+     */
+    public static double safeNodeHeight(final Tree tree, final Node node) {
+        if (node.getNodeHeight() > 0.0) {
+            return node.getNodeHeight();
+        }
+        return TreeUtilities.nodeDistance(node);
+    }
+    
+	private static void putCharAtLevel(PrintWriter out, int level, char c,
+            int[] position) {
+        int n = position[level] - 1;
+        for (int i = 0; i < n; i++) {
+            out.print(' ');
+        }
+        out.print(c);
+    }
+	
+	private static void printlnNodeWithNumberAndLabel(PrintWriter out, Node node, int level,
+            int numExternalNodes, boolean[] umbrella, int[] position) {
+        for (int i = 0; i < level - 1; i++) {
+            if (umbrella[i]) {
+                putCharAtLevel(out, i, '|', position);
+            } else {
+                putCharAtLevel(out, i, ' ', position);
+            }
+        }
+
+        putCharAtLevel(out, level - 1, '+', position);
+
+        int branchNumber;
+        if (node.isLeaf()) {
+            branchNumber = node.getNumber() + 1;
+        } else {
+            branchNumber = node.getNumber() + 1 + numExternalNodes;
+        }
+
+        String numberAsString = Integer.toString(branchNumber);
+
+        int numDashs = position[level] - numberAsString.length();
+
+        for (int i = 0; i < numDashs ; i++) {
+            out.print('-');
+        }
+        out.print(numberAsString);
+
+        if (node.isLeaf()) {
+            out.println(" " + node.getIdentifier());
+        } else {
+            if (!node.getIdentifier().equals(Identifier.ANONYMOUS)) {
+                out.print("(" + node.getIdentifier() + ")");
+            }
+            out.println();
+        }
+    }
+	private static void printNodeInASCII(PrintWriter out, Node node, int level, int m, int maxm,
+            int numExternalNodes, boolean[] umbrella, int[] position, double proportion, int minLength) {
+        position[level] = (int) (node.getBranchLength() * proportion);
+
+        if (position[level] < minLength) {
+            position[level] = minLength;
+        }
+
+        if (node.isLeaf()) // external branch
+        {
+            if (m == maxm - 1) {
+                umbrella[level - 1] = true;
+            }
+
+            printlnNodeWithNumberAndLabel(out, node, level, numExternalNodes, umbrella, position);
+
+            if (m == 0) {
+                umbrella[level - 1] = false;
+            }
+        } else // internal branch
+        {
+            for (int n = node.getChildCount() - 1; n > -1; n--) {
+                printNodeInASCII(out, node.getChild(n), level + 1, n, node.getChildCount(),
+                        numExternalNodes, umbrella, position, proportion, minLength);
+
+                if (m == maxm - 1 && n == node.getChildCount() / 2) {
+                    umbrella[level - 1] = true;
+                }
+
+                if (n != 0) {
+                    if (n == node.getChildCount() / 2) {
+                        printlnNodeWithNumberAndLabel(out, node, level, numExternalNodes, umbrella, position);
+                    } else {
+                        for (int i = 0; i < level + 1; i++) {
+                            if (umbrella[i]) {
+                                putCharAtLevel(out, i, '|', position);
+                            } else {
+                                putCharAtLevel(out, i, ' ', position);
+                            }
+                        }
+                        out.println();
+                    }
+                }
+
+                if (m == 0 && n == node.getChildCount() / 2) {
+                    umbrella[level - 1] = false;
+                }
+            }
+        }
+    }
+	
+	// Print picture of current tree in ASCII
+    public static void printASCII(Tree tree, PrintWriter out) {
+        tree.createNodeList();
+
+        int numExternalNodes = tree.getExternalNodeCount();
+        int numInternalNodes = tree.getInternalNodeCount();
+        int numBranches = numInternalNodes + numExternalNodes - 1;
+
+        boolean[] umbrella = new boolean[numExternalNodes];
+        int[] position = new int[numExternalNodes];
+
+        int minLength = (Integer.toString(numBranches)).length() + 1;
+
+        int MAXCOLUMN = 40;
+        Node root = tree.getRoot();
+        if (root.getNodeHeight() == 0.0) {
+            NodeUtils.lengths2Heights(root);
+        }
+        double proportion = (double) MAXCOLUMN / root.getNodeHeight();
+
+        for (int n = 0; n < numExternalNodes; n++) {
+            umbrella[n] = false;
+        }
+
+        position[0] = 1;
+        for (int i = root.getChildCount() - 1; i > -1; i--) {
+            printNodeInASCII(out, root.getChild(i), 1, i, root.getChildCount(),
+                    numExternalNodes, umbrella, position, proportion, minLength);
+            if (i != 0) {
+                putCharAtLevel(out, 0, '|', position);
+                out.println();
+            }
+        }
+    }
 	public static void printNH(PrintWriter out, Tree tree, Node node,
 			boolean printLengths, boolean printInternalLabels,
 			boolean printCladeSupport) {
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/tree/WeightedTree.java b/src/main/java/es/uvigo/darwin/jmodeltest/tree/WeightedTree.java
new file mode 100644
index 0000000..a53d84d
--- /dev/null
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/tree/WeightedTree.java
@@ -0,0 +1,60 @@
+/*
+Copyright (C) 2009  Diego Darriba
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package es.uvigo.darwin.jmodeltest.tree;
+
+import pal.tree.Tree;
+
+/**
+ *  This class represents a weighted PAL Tree
+ * 
+ * @author diego
+ */
+public class WeightedTree {
+
+    /** The tree. */
+    private Tree tree;
+    /** The weight. */
+    private double weight;
+
+    public Tree getTree() {
+        return tree;
+    }
+
+    public void setTree(Tree tree) {
+        this.tree = tree;
+    }
+
+    public double getWeight() {
+        return weight;
+    }
+
+    public void setWeight(double weight) {
+        this.weight = weight;
+    }
+
+    /**
+     * Instantiates a new weighted tree.
+     *
+     * @param tree the tree
+     * @param weight the weight
+     */
+    public WeightedTree(Tree tree, double weight) {
+        this.tree = tree;
+        this.weight = weight;
+    }
+}
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/utilities/FixedBitSet.java b/src/main/java/es/uvigo/darwin/jmodeltest/utilities/FixedBitSet.java
new file mode 100644
index 0000000..88826ad
--- /dev/null
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/utilities/FixedBitSet.java
@@ -0,0 +1,268 @@
+package es.uvigo.darwin.jmodeltest.utilities;
+
+import java.util.Arrays;
+
+/**
+ * A bit-set of fixed size. Size is determined on creation.
+ *
+ * @author Joseph Heled
+ * @version $Id: FixedBitSet.java 591 2006-12-21 02:39:18Z pepster $
+ */
+public class FixedBitSet implements Comparable<FixedBitSet> {
+    int[] bits;
+    int size;
+    //private int intSize = Integer.SIZE;
+
+    private final static int ADDRESS_BITS_PER_UNIT = 5;
+    private final static int BITS_PER_UNIT = 1 << ADDRESS_BITS_PER_UNIT;
+    private final static int BIT_INDEX_MASK = BITS_PER_UNIT - 1;
+
+
+    private static int unitIndex(int bitIndex) {
+        return bitIndex >> ADDRESS_BITS_PER_UNIT;
+    }
+
+    private int countBits(int b) {
+        int sum = 0;
+
+        while (b != 0) {
+            // remove most significant bit
+            b = b & (b - 1);
+            ++sum;
+        }
+        return sum;
+    }
+
+    /**
+     * Given a bit index, return a unit that masks that bit in its unit.
+     * @return the mask
+     */
+    private static int bit(int bitIndex) {
+        return 1 << (bitIndex & BIT_INDEX_MASK);
+    }
+
+    public FixedBitSet(int size) {
+        this.size = size;
+        bits = new int[(unitIndex(size - 1) + 1)];
+    }
+
+    public FixedBitSet(FixedBitSet bs) {
+        bits = bs.bits.clone();
+        size = bs.size;
+    }
+
+
+    public void set(int position) {
+        int unitIndex = unitIndex(position);
+        bits[unitIndex] |= bit(position);
+    }
+
+    public void clear(int position) {
+        int unitIndex = unitIndex(position);
+        bits[unitIndex] &= ~bit(position);
+    }
+
+    /**
+     * @param bitset
+     * @return true if bitset contains this set (this <= bitset)
+     */
+    public boolean setInclusion(final FixedBitSet bitset) {
+        for (int k = 0; k < bits.length; ++k) {
+            if (bits[k] != (bits[k] & bitset.bits[k])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void union(FixedBitSet b) {
+        for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) {
+            bits[k] |= b.bits[k];
+        }
+    }
+
+    public void intersect(FixedBitSet b) {
+        for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) {
+            bits[k] &= b.bits[k];
+        }
+    }
+
+    public void setMinus(FixedBitSet b) {
+        for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) {
+            bits[k] &= ~b.bits[k];
+        }
+    }
+
+    public int intersectCardinality(FixedBitSet b) {
+        int c = 0;
+        for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) {
+            c += countBits(bits[k] & b.bits[k]);
+        }
+        return c;
+    }
+
+    public static FixedBitSet complement(FixedBitSet b) {
+        FixedBitSet t = new FixedBitSet(b);
+        t.complement();
+        return t;
+    }
+
+    public void complement() {
+        int k;
+        for (k = 0; k < bits.length - 1; ++k) {
+            bits[k] = ~ bits[k];
+        }
+
+        bits[k] = ~bits[k];
+        // reset all higher order bits
+        final int mask = bit(size) - 1;
+        if( mask != 0 ) {
+            bits[k] &= mask;
+        }
+    }
+
+    private final static byte firstBitLocation[] = {
+            -1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+            4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+
+    private int firstOnBit(int i) {
+        for (int k = 0; k < 4; ++k) {
+            char b = (char) (i & 0xff);
+            if (b != 0) {
+                return 8 * k + firstBitLocation[b];
+            }
+            i = i >> 8;
+        }
+        return -1;
+    }
+
+    /**
+     * Iteration helper. A typical iteration on set bits might be
+     * FixedBitSet b;
+     * for(int i = b.nextOnBit(0); i >= 0; i = b.nextOnBit(i+1)) ...
+     *
+     * @param fromIndex
+     * @return Next set member whose index is >= fromIndex. -1 if none.
+     */
+    public int nextOnBit(int fromIndex) {
+        int u = unitIndex(fromIndex);
+        int testIndex = (fromIndex & BIT_INDEX_MASK);
+        int unit = bits[u] >> testIndex;
+
+        if (unit == 0) {
+            testIndex = 0;
+
+            while ((unit == 0) && (u < bits.length - 1))
+                unit = bits[++u];
+        }
+
+        if (unit == 0)
+            return -1;
+
+        testIndex += firstOnBit(unit);
+        return ((u * BITS_PER_UNIT) + testIndex);
+    }
+
+    public int cardinality() {
+        int sum = 0;
+        for (int b : bits) {
+            sum += countBits(b);
+        }
+        return sum;
+    }
+
+    public boolean contains(final int i) {
+        final int unitIndex = unitIndex(i);
+        return (bits[unitIndex] & bit(i)) != 0;
+    }
+
+    @Override
+    public int hashCode() {
+        int code = 0;
+
+        for (int bit : bits) {
+            code = code ^ bit;
+        }
+        return code;
+    }
+
+    @Override
+    public boolean equals(Object x) {
+        if (x instanceof FixedBitSet) {
+            final FixedBitSet b = (FixedBitSet) x;
+
+            return b.size == size && Arrays.equals(bits, b.bits);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder rep = new StringBuilder();
+        rep.append("{");
+        for (int b = 0; b < size; ++b) {
+            if (contains(b)) {
+                if (rep.length() > 0) {
+                    rep.append("," + b);
+                } else {
+                    rep.append("" + b);
+                }
+            }
+        }
+        rep.append("}");
+        return rep.toString();
+    }
+    
+    public String splitRepresentation() {
+        StringBuilder rep = new StringBuilder();
+        for (int b = 0; b < size; ++b) {
+            if (contains(b)) {
+                rep.append("*");
+            }
+            else {
+                rep.append("-");
+            }
+        }
+        return rep.toString();
+    }
+
+    public int compareTo(FixedBitSet fbs) {
+        int minSize;
+        int defaultValue;
+        if (size < fbs.size) {
+            minSize = size;
+            defaultValue = -1;
+        } else {
+            minSize = fbs.size;
+            if (size == fbs.size)
+                defaultValue = 0;
+            else
+                defaultValue = 1;
+        }
+        
+        for (int i = 0; i < minSize; i++) {
+            if (this.contains(i) && !fbs.contains(i)) {
+                return -1;
+            }
+            if (!this.contains(i) && fbs.contains(i)) {
+                return 1;
+            }
+        }
+        return defaultValue;
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/es/uvigo/darwin/jmodeltest/utilities/MyFormattedOutput.java b/src/main/java/es/uvigo/darwin/jmodeltest/utilities/MyFormattedOutput.java
new file mode 100644
index 0000000..edeb069
--- /dev/null
+++ b/src/main/java/es/uvigo/darwin/jmodeltest/utilities/MyFormattedOutput.java
@@ -0,0 +1,181 @@
+/*
+Copyright (C) 2009  Diego Darriba
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package es.uvigo.darwin.jmodeltest.utilities;
+
+import java.io.PrintWriter;
+
+import pal.io.FormattedOutput;
+
+/**
+ * The Class MyFormattedOutput.
+ */
+public class MyFormattedOutput {
+
+    /** The Constant NAN. */
+    private static final String NAN = "NaN";
+    /** The formatter. */
+    private static FormattedOutput formatter;
+
+    static {
+        formatter = FormattedOutput.getInstance();
+    }
+
+    /**
+     * Space.
+     * 
+     * @param size the size
+     * @param c the c
+     * 
+     * @return the string
+     */
+    public static String space(int size, char c) {
+        return FormattedOutput.space(size, c);
+    }
+
+    /**
+     * Gets the decimal string.
+     * 
+     * @param number the number
+     * @param width the width
+     * 
+     * @return the decimal string
+     */
+    public static String getDecimalString(double number, int width) {
+        String strValue;
+        if (Double.isNaN(number))//.isInfinite(number))
+        {
+            strValue = NAN;
+        } else {
+            strValue = formatter.getDecimalString(number, width);
+        }
+
+        return strValue;
+    }
+
+    /**
+     * Display decimal.
+     * 
+     * @param out the out
+     * @param number the number
+     * @param width the width
+     * 
+     * @return the int
+     */
+    public static int displayDecimal(PrintWriter out, double number, int width) {
+        int result = 0;
+        if (Double.isNaN(number)) {
+            formatter.displayLabel(out, NAN, width);
+            result = NAN.length();
+        } else {
+            result = formatter.displayDecimal(out, number, width);
+        }
+
+        return result;
+    }
+
+    /**
+     * turns an integer into a String, aligned to a reference number,
+     * (introducing space at the left side)
+     *
+     * @param num number to be printed
+     * @param maxNum reference number
+     */
+    public static String getIntegerString(int num, int maxNum) {
+        StringBuffer sb = new StringBuffer();
+        int lenNum = Integer.toString(num).length();
+        int lenMaxNum = Integer.toString(maxNum).length();
+
+        if (lenNum < lenMaxNum) {
+            for (int i = 0; i < num; i++) {
+                sb.append(' ');
+            }
+        }
+        sb.append(num);
+
+        return sb.toString();
+    }
+
+    /**
+     * print integer, aligned to a reference number,
+     * (introducing space at the left side)
+     *
+     * @param out output stream
+     * @param num number to be printed
+     * @param maxNum reference number
+     */
+    public static void displayInteger(PrintWriter out, int num, int maxNum) {
+        int lenNum = Integer.toString(num).length();
+        int lenMaxNum = Integer.toString(maxNum).length();
+
+        if (lenNum < lenMaxNum) {
+            multiplePrint(out, ' ', lenMaxNum - lenNum);
+        }
+        out.print(num);
+    }
+
+    /**
+     * print whitespace of length of a string displaying a given integer
+     *
+     * @param out the writer
+     * @param maxNum the number of white spaces
+     */
+    public static void displayIntegerWhite(PrintWriter out, int maxNum) {
+        int lenMaxNum = Integer.toString(maxNum).length();
+
+        multiplePrint(out, ' ', lenMaxNum);
+    }
+
+    /**
+     * print label with a prespecified length
+     * (label will be shortened or spaces will introduced, if necessary)
+     *
+     * @param out output stream
+     * @param label label to be printed
+     * @param width desired length
+     */
+    public static void displayLabel(PrintWriter out, String label, int width) {
+        int len = label.length();
+
+        if (len == width) {
+            // Print as is
+            out.print(label);
+        } else if (len < width) {
+            // fill rest with spaces
+            out.print(label);
+            multiplePrint(out, ' ', width - len);
+        } else {
+            // Print first width characters
+            for (int i = 0; i < width; i++) {
+                out.print(label.charAt(i));
+            }
+        }
+    }
+
+    /**
+     * repeatedly print a character
+     *
+     * @param out output stream
+     * @param c   character
+     * @param num number of repeats
+     */
+    public static void multiplePrint(PrintWriter out, char c, int num) {
+        for (int i = 0; i < num; i++) {
+            out.print(c);
+        }
+    }
+}
diff --git a/src/main/resources/CHANGELOG b/src/main/resources/CHANGELOG
index a2d38d3..7f87e41 100644
--- a/src/main/resources/CHANGELOG
+++ b/src/main/resources/CHANGELOG
@@ -1,3 +1,9 @@
+3 Mar 2016 Version 2.1.10 Revision 20160303
+
+  * Fixed bug with sequences where the 8-char name prefixes are equal
+  * Added warning when the logging is disabled on runtime
+  * Added win32 PhyML binary version to compatibility list
+
 15 Jan 2016 Version 2.1.9 Revision 20160115
 
   * Added automatic search for PhyML binary in /usr/bin
diff --git a/src/main/resources/README b/src/main/resources/README
index 1d4fd02..77d78c0 100644
--- a/src/main/resources/README
+++ b/src/main/resources/README
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
-jModelTest 2.1.9 Readme - Jan/15/2016
+jModelTest 2.1.10 Readme - Mar/3/2016
 
 Diego Darriba (ddarriba at udc.es)
 Guillermo L. Taboada (taboada at udc.es)
diff --git a/src/main/resources/resources/template/index.html b/src/main/resources/resources/template/index.html
index 2d91ee1..bfe010c 100644
--- a/src/main/resources/resources/template/index.html
+++ b/src/main/resources/resources/template/index.html
@@ -377,7 +377,7 @@ ${aicConfidenceList}
     </div>
     <div class="rf-img">
     	<img class="distances-img" src="${aicRfImagePath}"/><br/>
-    	Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestAicModel.tree}&useBranchLengths=false">${bestAicModel.name} topology</a>.
+    	Relative Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestAicModel.tree}&useBranchLengths=false">${bestAicModel.name} topology</a>.
     </div>
     <div style="clear:both;"></div>
   </div><!--selection-distances-->
@@ -483,7 +483,7 @@ ${aiccConfidenceList}
     </div>
     <div class="rf-img">
     	<img class="distances-img" src="${aiccRfImagePath}"/><br/>
-    	Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestAiccModel.tree}&useBranchLengths=false">${bestAiccModel.name} topology</a>.
+    	Relative Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestAiccModel.tree}&useBranchLengths=false">${bestAiccModel.name} topology</a>.
     </div>
     <div style="clear:both;"></div>
   </div><!--selection-distances-->
@@ -591,7 +591,7 @@ ${bicConfidenceList}
     </div>
     <div class="rf-img">
     	<img class="distances-img" src="${bicRfImagePath}"/><br/>
-    	Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestBicModel.tree}&useBranchLengths=false">${bestBicModel.name} topology</a>.
+    	Relative Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestBicModel.tree}&useBranchLengths=false">${bestBicModel.name} topology</a>.
     </div>
     <div style="clear:both;"></div>
   </div><!--selection-distances-->
@@ -698,7 +698,7 @@ ${dtConfidenceList}
     </div>
     <div class="rf-img">
     	<img class="distances-img" src="${dtRfImagePath}"/><br/>
-    	Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestDtModel.tree}&useBranchLengths=false">${bestDtModel.name} topology</a>.
+    	Relative Robinson-Foulds distances histogram from the different topologies to <a href="http://www.phylowidget.org/full/?tree=${bestDtModel.tree}&useBranchLengths=false">${bestDtModel.name} topology</a>.
     </div>
     <div style="clear:both;"></div>
   </div><!--selection-distances-->

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



More information about the debian-med-commit mailing list