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 <[email protected]> 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 + * [email protected] + * @author David Posada, University of Vigo, Spain [email protected] | + * 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 + * [email protected] + * @author David Posada, University of Vigo, Spain [email protected] | + * 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 ([email protected]) Guillermo L. Taboada ([email protected]) 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 _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
