This is an automated email from the git hooks/post-receive script. tille pushed a commit to branch master in repository beast2-mcmc.
commit ef83e24a08a486b0c8a039ecabe3be4b0977abba Author: Andreas Tille <[email protected]> Date: Fri Dec 2 11:16:42 2016 +0100 Imported Upstream version 2.4.4+dfsg --- build.xml | 4 +- release/common/README.txt | 4 +- release/common/VERSION HISTORY.txt | 15 +- src/beast/app/BEASTVersion.java | 2 +- src/beast/app/BEASTVersion2.java | 2 +- src/beast/app/beastapp/BeastLauncher.java | 2 +- src/beast/app/beauti/AlignmentListInputEditor.java | 50 +---- src/beast/app/beauti/BeautiAlignmentProvider.java | 4 + src/beast/app/beauti/BeautiConfig.java | 7 +- src/beast/app/beauti/BeautiDoc.java | 77 +++++--- src/beast/app/beauti/GuessPatternDialog.java | 52 ++++-- src/beast/app/beauti/MRCAPriorInputEditor.java | 3 + src/beast/app/treeannotator/TreeAnnotator.java | 201 ++++++++++++--------- src/beast/app/treeannotator/TreeSetParser.java | 3 +- src/beast/app/util/Utils6.java | 12 +- src/beast/evolution/operators/NodeReheight.java | 2 +- src/beast/evolution/tree/Tree.java | 56 +++--- .../evolution/tree/TreeWithMetaDataLogger.java | 36 ++-- src/beast/util/AddOnManager.java | 116 ++++++------ src/beast/util/NexusParser.java | 32 ++-- src/beast/util/TreeParser.java | 34 ++-- src/beast/util/treeparser/Newick.g4 | 5 +- src/beast/util/treeparser/NewickBaseVisitor.java | 2 +- src/beast/util/treeparser/NewickLexer.java | 92 ++++++---- src/beast/util/treeparser/NewickParser.java | 27 +-- src/beast/util/treeparser/NewickVisitor.java | 2 +- .../evolution/alignment/FilteredAlignmentTest.java | 68 ++++++- src/test/beast/util/TreeParserTest.java | 14 ++ version.xml | 2 +- 29 files changed, 550 insertions(+), 376 deletions(-) diff --git a/build.xml b/build.xml index 420fe49..22b260a 100644 --- a/build.xml +++ b/build.xml @@ -242,8 +242,8 @@ <!-- Release --> - <property name="version" value="2.4.3" /> - <property name="version_number" value="2.4.3" /> + <property name="version" value="2.4.4" /> + <property name="version_number" value="2.4.4" /> <property name="release_dir" value="release" /> <property name="copyright" value="Beast 2 development team 2011-2016" /> diff --git a/release/common/README.txt b/release/common/README.txt index 9e7954b..f2c540a 100644 --- a/release/common/README.txt +++ b/release/common/README.txt @@ -1,7 +1,7 @@ - BEAST v2.4.3 2016 + BEAST v2.4.4 2016 Beast 2 development team 2011-2016 -Last updated: August 2016 +Last updated: November 2016 Contents: 1) INTRODUCTION diff --git a/release/common/VERSION HISTORY.txt b/release/common/VERSION HISTORY.txt index c795a5c..77f811e 100644 --- a/release/common/VERSION HISTORY.txt +++ b/release/common/VERSION HISTORY.txt @@ -1,14 +1,23 @@ - BEAST v2.4.3 2016 + BEAST v2.4.4 2016 Beast 2 development team 2011-2016 Version History -Last updated: August 2016 +Last updated: November 2016 All issues can be viewed at https://github.com/CompEvol/beast2/issues ================================================================================ +Version 2.4.4 November 2016 + Fix that prevented starting any BEAST application on Mac Sierra + + Smooth out some issues with importing Nexus files in BEAUti + + TreeAnnotator fix for use with user defined trees to annotate + + Allow smaller log files by logging fewer significant digits of metadata + Version 2.4.3 August 2016 BEAUti - Support for tip data sampling by setting 'tipsonly' in MRCA Priors + Support for tip date sampling by setting 'tipsonly' in MRCA Priors Allow packages to specify priors, e.g. multi-monophyletic constraints in BEASTLabs Allow packages to specify file importers, which allows microsattelite support through the BEASTvntr package Gamma distribution allows multiple parameterisations diff --git a/src/beast/app/BEASTVersion.java b/src/beast/app/BEASTVersion.java index 44a8abd..609d8d7 100644 --- a/src/beast/app/BEASTVersion.java +++ b/src/beast/app/BEASTVersion.java @@ -19,7 +19,7 @@ public class BEASTVersion extends Version { /** * Version string: assumed to be in format x.x.x */ - private static final String VERSION = "2.4.3"; + private static final String VERSION = "2.4.4"; private static final String DATE_STRING = "2002-2016"; diff --git a/src/beast/app/BEASTVersion2.java b/src/beast/app/BEASTVersion2.java index d91d2b6..42aea5b 100644 --- a/src/beast/app/BEASTVersion2.java +++ b/src/beast/app/BEASTVersion2.java @@ -9,7 +9,7 @@ public class BEASTVersion2 extends BEASTVersion { /** * Version string: assumed to be in format x.x.x */ - private static final String VERSION = "2.4.3"; + private static final String VERSION = "2.4.4"; private static final String DATE_STRING = "2002-2016"; diff --git a/src/beast/app/beastapp/BeastLauncher.java b/src/beast/app/beastapp/BeastLauncher.java index ef96819..69d0c22 100644 --- a/src/beast/app/beastapp/BeastLauncher.java +++ b/src/beast/app/beastapp/BeastLauncher.java @@ -29,7 +29,7 @@ import beast.app.util.Utils6; * remainder of BEAST can be compiled against Java 1.8 * **/ public class BeastLauncher { - private static String getVersion() {return "2.4.3";} + private static String getVersion() {return "2.4.4";} private static String getMajorVersion() {return "2.4";} private static String pathDelimiter; diff --git a/src/beast/app/beauti/AlignmentListInputEditor.java b/src/beast/app/beauti/AlignmentListInputEditor.java index 8d73a4f..61ccead 100644 --- a/src/beast/app/beauti/AlignmentListInputEditor.java +++ b/src/beast/app/beauti/AlignmentListInputEditor.java @@ -156,7 +156,7 @@ public class AlignmentListInputEditor extends ListInputEditor { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - addFiles(files); + addItem(files); } }); } // end filesDropped @@ -219,46 +219,6 @@ public class AlignmentListInputEditor extends ListInputEditor { return buttonBox; } - private void addFiles(File[] fileArray) { - List<BEASTInterface> beastObjects = null; - - List<BeautiAlignmentProvider> providers = doc.beautiConfig.alignmentProvider; - BeautiAlignmentProvider selectedProvider = null; - if (providers.size() == 1) { - selectedProvider = providers.get(0); - } else { - selectedProvider = (BeautiAlignmentProvider) JOptionPane.showInputDialog(this, "Select what to add", - "Add partition", - JOptionPane.QUESTION_MESSAGE, null, providers.toArray(), - providers.get(0)); - if (selectedProvider == null) { - return; - } - } - - beastObjects = selectedProvider.getAlignments(doc, fileArray); - - // create taxon sets, if any - if (beastObjects != null) { - for (BEASTInterface o : beastObjects) { - if (o instanceof Alignment) { - try { - BeautiDoc.createTaxonSet((Alignment) o, doc); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - // Component c = this; - if (beastObjects != null) { - refreshPanel(); - } - } - - - /** * This method just adds the two buttons (with add()) and does not add any glue or struts before or after. * @param box @@ -1095,13 +1055,17 @@ public class AlignmentListInputEditor extends ListInputEditor { @Override protected void addItem() { - List<BEASTInterface> beastObjects = doc.beautiConfig.selectAlignments(doc, this); + addItem(null); + } // addItem + + private void addItem(File[] fileArray) { + List<BEASTInterface> beastObjects = doc.beautiConfig.selectAlignments(doc, this, fileArray); // Component c = this; if (beastObjects != null) { refreshPanel(); } - } // addItem + } void delItem() { int[] selected = getTableRowSelection(); diff --git a/src/beast/app/beauti/BeautiAlignmentProvider.java b/src/beast/app/beauti/BeautiAlignmentProvider.java index 44681f8..81d568d 100644 --- a/src/beast/app/beauti/BeautiAlignmentProvider.java +++ b/src/beast/app/beauti/BeautiAlignmentProvider.java @@ -116,6 +116,10 @@ public class BeautiAlignmentProvider extends BEASTObject { * @return */ public List<BEASTInterface> getAlignments(BeautiDoc doc, File[] files) { + if (files == null) { + // merge "+ button" and "drag drop" function + return getAlignments(doc); + } if (importers == null) { initImporters(); } diff --git a/src/beast/app/beauti/BeautiConfig.java b/src/beast/app/beauti/BeautiConfig.java index 9101d0a..c5e5e09 100644 --- a/src/beast/app/beauti/BeautiConfig.java +++ b/src/beast/app/beauti/BeautiConfig.java @@ -1,6 +1,7 @@ package beast.app.beauti; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -165,11 +166,13 @@ public class BeautiConfig extends BEASTObject { } /** + * if fileArray == null, then use getAlignments(doc) * @param doc * @param parent + * @param fileArray * @return a list of alignments based on the user selected alignment provider */ - public List<BEASTInterface> selectAlignments(BeautiDoc doc, JComponent parent) { + public List<BEASTInterface> selectAlignments(BeautiDoc doc, JComponent parent, File[] fileArray) { List<BeautiAlignmentProvider> providers = alignmentProvider; BeautiAlignmentProvider selectedProvider = null; if (providers.size() == 1) { @@ -183,7 +186,7 @@ public class BeautiConfig extends BEASTObject { return null; } } - List<BEASTInterface> beastObjects = selectedProvider.getAlignments(doc); + List<BEASTInterface> beastObjects = selectedProvider.getAlignments(doc, fileArray); // create taxon sets, if any if (beastObjects != null) { for (BEASTInterface o : beastObjects) { diff --git a/src/beast/app/beauti/BeautiDoc.java b/src/beast/app/beauti/BeautiDoc.java index c1a6d86..6b7a909 100644 --- a/src/beast/app/beauti/BeautiDoc.java +++ b/src/beast/app/beauti/BeautiDoc.java @@ -4,7 +4,6 @@ package beast.app.beauti; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; @@ -69,8 +68,8 @@ import beast.evolution.substitutionmodel.SubstitutionModel; import beast.evolution.tree.TraitSet; import beast.evolution.tree.Tree; import beast.math.distributions.MRCAPrior; +import beast.math.distributions.Normal; import beast.math.distributions.ParametricDistribution; -import beast.math.distributions.Uniform; import beast.util.JSONProducer; import beast.util.NexusParser; import beast.util.XMLParser; @@ -131,6 +130,11 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { private String templateName = null; private String templateFileName = STANDARD_TEMPLATE; + // used to scale *BEAST and StarBEAST2 species (tree) operator rates + // so that 20% of operator weights is dedicated to species operators + final private double speciesOperatorsFraction = 0.20; + private double speciesOperatorsScale = -1.0; + Map<String, String> tipTextMap = new HashMap<>(); /** @@ -720,6 +724,11 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { public void save(File file) throws IOException { determinePartitions(); scrubAll(false, false); + + if (autoUpdateOperatorWeights) { + reweightSpeciesPartitionOperators(); + } + // String xml = new XMLProducer().toXML(mcmc.get(), ); String spec = null; if (file.getPath().toLowerCase().endsWith(".json")) { @@ -730,6 +739,10 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { FileWriter outfile = new FileWriter(file); outfile.write(spec); outfile.close(); + + if (autoUpdateOperatorWeights) { + revertSpeciesPartitionOperators(); + } } // save private String toJSON() { @@ -1130,7 +1143,7 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { // process MRCA priors for (String id : pluginmap.keySet()) { - if (id.endsWith(".prior")) { + if (id != null && id.endsWith(".prior")) { BEASTInterface beastObject = pluginmap.get(id); if (beastObject instanceof MRCAPrior) { MRCAPrior prior = (MRCAPrior) beastObject; @@ -1177,7 +1190,7 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { templates.add(beautiConfig.hyperPriorTemplate); for (BEASTInterface beastObject : pluginmap.values()) { if (beastObject instanceof RealParameter) { - if (beastObject.getID().startsWith("parameter.")) { + if (beastObject.getID() != null && beastObject.getID().startsWith("parameter.")) { PartitionContext context = new PartitionContext(beastObject.getID().substring("parameter.".length())); applyBeautiRules(templates, isInitial, context); } @@ -1195,10 +1208,6 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { } catch (Exception e) { Log.err.println(e.getMessage()); } - - if (autoUpdateOperatorWeights) { - reweightSpeciesPartitionOperators(); - } } // scrubAll protected void setUpActivePlugins() { @@ -1494,33 +1503,43 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { * *BEAST analyses, this bit of code has no effect. */ private void reweightSpeciesPartitionOperators() { - if (!(mcmc.get() instanceof MCMC)) { - return; - } + if (!(mcmc.get() instanceof MCMC)) return; + List<Operator> speciesOperators = new ArrayList<>(); - double totalWeight = 0; - double speciesWeight = 0; + double geneOperatorsWeight = 0; + double speciesOperatorsWeight = 0; for (Operator operator : ((MCMC)mcmc.get()).operatorsInput.get()) { if (operator.getID().endsWith("Species")) { speciesOperators.add(operator); - speciesWeight += operator.getWeight(); + speciesOperatorsWeight += operator.getWeight(); + } else { + geneOperatorsWeight += operator.getWeight(); } - totalWeight += operator.getWeight(); } - if (speciesWeight > 0 && speciesWeight < totalWeight) { - // we have a Species-related operator AND an alignment - // rescale weights so that 20% of operator weights is dedicated to Species operators - final double fraction = 0.2; - //double scale = fraction/(1.0 - fraction) / (speciesWeight / (totalWeight - speciesWeight)); - double scale = fraction /(1-fraction) * ((totalWeight-speciesWeight) / speciesWeight); + // we have a Species-related operator AND an alignment + if (speciesOperatorsWeight > 0 && geneOperatorsWeight > 0) { + final double targetWeight = (speciesOperatorsFraction * geneOperatorsWeight) / (1.0 - speciesOperatorsFraction); + speciesOperatorsScale = targetWeight / speciesOperatorsWeight; for (Operator operator : speciesOperators) { - operator.m_pWeight.setValue(scale * operator.getWeight(), operator); + operator.m_pWeight.setValue(operator.getWeight() * speciesOperatorsScale, operator); } + } else { + speciesOperatorsScale = -1.0; } - } + private void revertSpeciesPartitionOperators() { + if (!(mcmc.get() instanceof MCMC)) return; + if (speciesOperatorsScale < 0.0) return; + + for (Operator operator : ((MCMC)mcmc.get()).operatorsInput.get()) { + if (operator.getID().endsWith("Species")) { + operator.m_pWeight.setValue(operator.getWeight() / speciesOperatorsScale, operator); + } + } + } + public BEASTInterface addAlignmentWithSubnet(PartitionContext context, BeautiSubTemplate template) { BEASTInterface data = template.createSubNet(context, true); alignments.add((Alignment) data); @@ -2451,6 +2470,14 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { public void addMRCAPrior(MRCAPrior mrcaPrior) { Tree tree = (Tree) pluginmap.get("Tree.t:" + alignments.get(0).getID()); + if (tree == null) { + for (String key : pluginmap.keySet()) { + if (key.startsWith("Tree.t:")) { + tree = (Tree) pluginmap.get(key); + break; + } + } + } // TODO: make sure we have the appropriate tree CompoundDistribution prior = (CompoundDistribution) pluginmap.get("prior"); mrcaPrior.treeInput.setValue(tree, mrcaPrior); @@ -2470,13 +2497,13 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider { taxaset.put(taxa.get(i).getID(), taxa.get(i)); } } - if (distr instanceof Uniform && ((Uniform)distr).lowerInput.get() == ((Uniform)distr).upperInput.get()) { + if (distr instanceof Normal && (Double.isInfinite(((Normal)distr).sigmaInput.get().getValue()))) { // it is a 'fixed' calibration, no need to add a distribution } else { prior.pDistributions.setValue(mrcaPrior, prior); } } - if (t.taxonsetInput.get().size() == 1) { + if (t.taxonsetInput.get().size() == 1 && distr != null) { // it is a calibration on a tip -- better start sampling that tip TipDatesRandomWalker operator = new TipDatesRandomWalker(); t.initAndValidate(); diff --git a/src/beast/app/beauti/GuessPatternDialog.java b/src/beast/app/beauti/GuessPatternDialog.java index 4653762..3811c4b 100644 --- a/src/beast/app/beauti/GuessPatternDialog.java +++ b/src/beast/app/beauti/GuessPatternDialog.java @@ -1,10 +1,6 @@ package beast.app.beauti; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; +import java.awt.*; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -33,18 +29,25 @@ import beast.core.util.Log; public class GuessPatternDialog extends JDialog { private static final long serialVersionUID = 1L; - public static final String EXAMPLE_FORMAT = "<html>A proper trait file is tab delimited. <br>" - + "The first row is always <font color=red>traits</font> followed by the keyword <br>" - + "(e.g. <font color=red>species</font> in *BEAST) in the second column and separated <br>" - + "by <font color=red>tab</font>. The rest rows are mapping taxa to species, which list <br>" - + "taxon name in the first column and species name in the second column separated by <br>" - + "<font color=red>tab</font>. For example: <br>" + "traits\tspecies<br>" + "taxon1\tspeciesA<br>" - + "taxon2\tspeciesA<br>" + "taxon3\tspeciesB<br>" + "... ...<br>" - + "Once mapping file is loaded, the trait named by keyword <font color=red>species</font> <br>" - + "is displayed in the main panel, and the message of using *BEAST is also displayed on <br>" - + "the bottom of main frame.<br>" - + "For multi-alignment, the default of *BEAST is unlinking all models: substitution model, <br>" - + "clock model, and tree models.</html>"; + + private static String TRAIT_FILE_HELP_MESSAGE = + "This option allows trait values (such as species, tip dates and sample locations) " + + "to be specified using a file which links each taxon " + + "with a trait value. The file must contain one row per " + + "taxon, with each row containing the taxon name and the " + + "trait value separated by a TAB (not a space!) character.\n" + + "\n" + + "For instance, a file specifying the ages of three taxa named " + + "taxonA, taxonB and taxonC should contain the following:\n" + + "\n" + + "taxonA 0.0\n" + + "taxonB 0.1\n" + + "taxonC 0.2\n" + + "\n" + + "where the gap between each taxon name and the numeric value " + + "representing the age must be a TAB."; + + public enum Status { canceled, pattern, trait @@ -206,8 +209,19 @@ public class GuessPatternDialog extends JDialog { JButton btnHelp = new JButton("?"); btnHelp.setToolTipText("Show format of trait file"); btnHelp.addActionListener(e -> { - JOptionPane.showMessageDialog(m_parent, EXAMPLE_FORMAT); - }); + JOptionPane pane = new JOptionPane() { + @Override + public int getMaxCharactersPerLineCount() { + return 70; + } + }; + pane.setMessage(TRAIT_FILE_HELP_MESSAGE); + pane.setMessageType(JOptionPane.INFORMATION_MESSAGE); + + JDialog dialog = pane.createDialog(this, "Message"); + dialog.setModal(true); + dialog.setVisible(true); + }); GridBagConstraints gbc_btnHelp = new GridBagConstraints(); gbc_btnHelp.insets = new Insets(0, 0, 5, 5); gbc_btnHelp.gridx = 4; diff --git a/src/beast/app/beauti/MRCAPriorInputEditor.java b/src/beast/app/beauti/MRCAPriorInputEditor.java index 18f0632..c8a00e5 100644 --- a/src/beast/app/beauti/MRCAPriorInputEditor.java +++ b/src/beast/app/beauti/MRCAPriorInputEditor.java @@ -166,6 +166,9 @@ public class MRCAPriorInputEditor extends InputEditor.Base { MRCAPrior prior = (MRCAPrior) list.get(itemNr); doc.disconnect(prior, "prior", "distribution"); doc.disconnect(prior, "tracelog", "log"); + if (prior.onlyUseTipsInput.get()) { + disableTipSampling(); + } doc.unregisterPlugin(prior); refreshPanel(); } diff --git a/src/beast/app/treeannotator/TreeAnnotator.java b/src/beast/app/treeannotator/TreeAnnotator.java index 5601b64..791989c 100644 --- a/src/beast/app/treeannotator/TreeAnnotator.java +++ b/src/beast/app/treeannotator/TreeAnnotator.java @@ -25,23 +25,8 @@ package beast.app.treeannotator; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; +import java.io.*; +import java.util.*; import javax.swing.JFrame; @@ -87,22 +72,85 @@ public class TreeAnnotator { abstract boolean hasNext(); abstract Tree next() throws IOException; abstract void reset() throws IOException; + + + String inputFileName; + int burninCount = 0; + int totalTrees = 0; + boolean isNexus = true; + + /** determine number of trees in the file, + * and number of trees to skip as burnin + * @throws IOException + * @throws FileNotFoundException **/ + void countTrees(int burninPercentage) throws IOException { + BufferedReader fin = new BufferedReader(new FileReader(new File(inputFileName))); + if (!fin.ready()) { + throw new IOException("File appears empty"); + } + String str = fin.readLine(); + if (!str.toUpperCase().trim().startsWith("#NEXUS")) { + // the file contains a list of Newick trees instead of a list in Nexus format + isNexus = false; + if (str.trim().length() > 0) { + totalTrees = 1; + } + } + while (fin.ready()) { + str = fin.readLine(); + if (isNexus) { + if (str.trim().toLowerCase().startsWith("tree ")) { + totalTrees++; + } + } else if (str.trim().length() > 0) { + totalTrees++; + } + } + fin.close(); + + burninCount = Math.max(0, (burninPercentage * totalTrees)/100); + + progressStream.println("Processing " + (totalTrees - burninCount) + " trees from file" + + (burninPercentage > 0 ? " after ignoring first " + burninPercentage + "% = " + burninCount + " trees." : ".")); + } + } class FastTreeSet extends TreeSet { int current = 0; Tree [] trees; - + public FastTreeSet(String inputFileName, int burninPercentage) throws IOException { - progressStream.println("0 25 50 75 100"); - progressStream.println("|--------------|--------------|--------------|--------------|"); - TreeSetParser parser = new TreeSetParser(burninPercentage, false); - Node [] roots = parser.parseFile(inputFileName); - trees = new Tree[roots.length]; - int i = 0; - for (Node root : roots) { - trees[i++] = new Tree(root); - } + this.inputFileName = inputFileName; + countTrees(burninPercentage); + + List<Tree> parsedTrees; + if (isNexus) { + NexusParser nexusParser = new NexusParser(); + nexusParser.parseFile(new File(inputFileName)); + parsedTrees = nexusParser.trees; + } else { + BufferedReader fin = new BufferedReader(new FileReader(inputFileName)); + parsedTrees = new ArrayList<>(); + while (fin.ready()) { + String line = fin.readLine().trim(); + + Tree thisTree; + try { + thisTree = new TreeParser(null, line, 0, false); + } catch (ArrayIndexOutOfBoundsException e) { + thisTree = new TreeParser(null, line, 1, false); + } + + parsedTrees.add(thisTree); + } + fin.close(); + } + + int treesToUse = parsedTrees.size() - burninCount; + trees = new Tree[treesToUse]; + for (int i=burninCount; i<parsedTrees.size(); i++) + trees[i-burninCount] = parsedTrees.get(i); } @Override @@ -127,55 +175,19 @@ public class TreeAnnotator { int lineNr; public Map<String, String> translationMap = null; public List<String> taxa; - - int burninCount = 0; - int totalTrees = 0; - boolean isNexus = true; - BufferedReader fin; - String inputFileName; + // label count origin for NEXUS trees int origin = -1; - + + BufferedReader fin; + MemoryFriendlyTreeSet(String inputFileName, int burninPercentage) throws IOException { this.inputFileName = inputFileName; - init(burninPercentage); - progressStream.println("Processing " + (totalTrees - burninCount) + " trees from file" + - (burninPercentage > 0 ? " after ignoring first " + burninPercentage + "% = " + burninCount + " trees." : ".")); - - + countTrees(burninPercentage); + + fin = new BufferedReader(new FileReader(inputFileName)); } - /** determine number of trees in the file, - * and number of trees to skip as burnin - * @throws IOException - * @throws FileNotFoundException **/ - private void init(int burninPercentage) throws IOException { - fin = new BufferedReader(new FileReader(new File(inputFileName))); - if (!fin.ready()) { - throw new IOException("File appears empty"); - } - String str = nextLine(); - if (!str.toUpperCase().trim().startsWith("#NEXUS")) { - // the file contains a list of Newick trees instead of a list in Nexus format - isNexus = false; - if (str.trim().length() > 0) { - totalTrees = 1; - } - } - while (fin.ready()) { - str = nextLine(); - if (isNexus) { - if (str.trim().toLowerCase().startsWith("tree ")) { - totalTrees++; - } - } else if (str.trim().length() > 0) { - totalTrees++; - } - } - fin.close(); - - burninCount = Math.max(0, (burninPercentage * totalTrees)/100); - } @Override void reset() throws FileNotFoundException { @@ -415,7 +427,7 @@ public class TreeAnnotator { // Messages to stderr, output to stdout - private static PrintStream progressStream = Log.err; + static PrintStream progressStream = Log.err; // private final String location1Attribute = "longLat1"; // private final String location2Attribute = "longLat2"; @@ -445,10 +457,6 @@ public class TreeAnnotator { totalTrees = 10000; totalTreesUsed = 0; - //progressStream.println("Reading trees (bar assumes 10,000 trees)..."); - - int stepSize = Math.max(totalTrees / 60, 1); - try { if (lowMemory) { treeSet = new MemoryFriendlyTreeSet(inputFileName, burninPercentage); @@ -461,7 +469,6 @@ public class TreeAnnotator { return; } - if (targetOption != Target.USER_TARGET_TREE) { try { treeSet.reset(); @@ -502,12 +509,26 @@ public class TreeAnnotator { cladeSystem.calculateCladeCredibilities(totalTreesUsed); progressStream.println("Total trees have " + totalTrees + ", where " + totalTreesUsed + " are used."); -// if (burninPercentage > 0) { -// progressStream.println("Ignoring first " + burninPercentage + "% trees."); -// } progressStream.println("Total unique clades: " + cladeSystem.getCladeMap().keySet().size()); progressStream.println(); + } else { + // even when a user specificed target tree is provided we still need to count the totalTreesUsed for subsequent steps. + treeSet.reset(); + while (treeSet.hasNext()) { + Tree tree = treeSet.next(); + tree.getLeafNodeCount(); + if (tree.getDirectAncestorNodeCount() > 0 && !SAmode) { + SAmode = true; + Log.err.println("A tree with a sampled ancestor is found. Turning on\n the sampled ancestor " + + "summary analysis."); + if (heightsOption == HeightsSummary.CA_HEIGHTS) { + throw new RuntimeException("The common ancestor height is not \n available for trees with sampled " + + "ancestors. Please choose \n another height summary option"); + } + } + totalTreesUsed++; + } } Tree targetTree = null; @@ -555,13 +576,13 @@ public class TreeAnnotator { progressStream.println("0 25 50 75 100"); progressStream.println("|--------------|--------------|--------------|--------------|"); - stepSize = Math.max(totalTreesUsed / 60, 1); + int stepSize = Math.max(totalTreesUsed / 60, 1); int reported = 0; // this call increments the clade counts and it shouldn't // this is remedied with removeClades call after while loop below cladeSystem = new CladeSystem(targetTree); - int totalTreesUsed = 0; + int totalTreesUsedNew = 0; try { int counter = 0; treeSet.reset(); @@ -578,14 +599,13 @@ public class TreeAnnotator { } progressStream.flush(); } - totalTreesUsed++; + totalTreesUsedNew++; counter++; } cladeSystem.removeClades(targetTree.getRoot(), true); - //progressStream.println("totalTreesUsed=" + totalTreesUsed); - this.totalTreesUsed = totalTreesUsed; - cladeSystem.calculateCladeCredibilities(totalTreesUsed); + this.totalTreesUsed = totalTreesUsedNew; + cladeSystem.calculateCladeCredibilities(totalTreesUsedNew); } catch (Exception e) { Log.err.println("Error Parsing Input Tree: " + e.getMessage()); return; @@ -599,7 +619,7 @@ public class TreeAnnotator { annotateTree(cladeSystem, targetTree.getRoot(), null, heightsOption); if( heightsOption == HeightsSummary.CA_HEIGHTS ) { - setTreeHeightsByCA(targetTree); + setTreeHeightsByCA(targetTree, targetOption); } } catch (Exception e) { e.printStackTrace(); @@ -639,7 +659,7 @@ public class TreeAnnotator { processMetaData(child); } Set<String> metaDataNames = node.getMetaDataNames(); - if (metaDataNames != null) { + if (metaDataNames != null && !metaDataNames.isEmpty()) { String metadata = ""; for (String name : metaDataNames) { Object value = node.getMetaData(name); @@ -1490,7 +1510,7 @@ public class TreeAnnotator { boolean handleAttribute(Node node, String attributeName, double[] values); } - boolean setTreeHeightsByCA(Tree targetTree) throws IOException + boolean setTreeHeightsByCA(Tree targetTree, Target targetOption) throws IOException { progressStream.println("Setting node heights..."); progressStream.println("0 25 50 75 100"); @@ -1554,7 +1574,10 @@ public class TreeAnnotator { counter++; } - targetTree.initAndValidate(); + + if (targetOption != Target.USER_TARGET_TREE) + targetTree.initAndValidate(); + cladeSystem.removeClades(targetTree.getRoot(), true); for (int k = 0; k < clades; ++k) { ths[k] /= totalTreesUsed; diff --git a/src/beast/app/treeannotator/TreeSetParser.java b/src/beast/app/treeannotator/TreeSetParser.java index af038c7..d42943c 100644 --- a/src/beast/app/treeannotator/TreeSetParser.java +++ b/src/beast/app/treeannotator/TreeSetParser.java @@ -30,6 +30,7 @@ import java.util.Vector; import beast.core.util.Log; import beast.evolution.tree.Node; +import beast.evolution.tree.Tree; public class TreeSetParser { /** @@ -281,7 +282,7 @@ public class TreeSetParser { String s = fin.readLine(); fileRead += s.length(); if (fileRead > fileMarked - 10) { - Log.warning.print("*"); + TreeAnnotator.progressStream.print("*"); fileMarked += fileStep; k++; } diff --git a/src/beast/app/util/Utils6.java b/src/beast/app/util/Utils6.java index fb32c7e..eeb109d 100644 --- a/src/beast/app/util/Utils6.java +++ b/src/beast/app/util/Utils6.java @@ -119,12 +119,12 @@ public class Utils6 { // /Library/Frameworks/CUDA.framework // /Developer/NVIDIA // /usr/local/cuda + // there is evidence of CUDA being installed on this computer + // try to create a BeagleTreeLikelihood using a separate process + try { if (new File("/Library/Frameworks/CUDA.framework").exists() || new File("/Developer/NVIDIA").exists() || new File("/usr/local/cuda").exists()) { - // there is evidence of CUDA being installed on this computer - // try to create a BeagleTreeLikelihood using a separate process - try { String java = System.getenv("java.home"); if (java == null) { java ="/usr/bin/java"; @@ -157,9 +157,9 @@ public class Utils6 { return false; } } - catch (Exception err) { - err.printStackTrace(); - } + } + catch (Exception err) { + err.printStackTrace(); } } diff --git a/src/beast/evolution/operators/NodeReheight.java b/src/beast/evolution/operators/NodeReheight.java index 88b429b..845499a 100644 --- a/src/beast/evolution/operators/NodeReheight.java +++ b/src/beast/evolution/operators/NodeReheight.java @@ -40,7 +40,7 @@ public class NodeReheight extends TreeOperator { final List<Taxon> list = taxonSetInput.get().taxonsetInput.get(); if (list.size() <= 1) { - Log.warning.println("NodeReheight operator requires at least 2 taxa while the taxon set (id=" + taxonSetInput.get().getID() +") has only " + list.size() + " taxa. " + Log.err.println("NodeReheight operator requires at least 2 taxa while the taxon set (id=" + taxonSetInput.get().getID() +") has only " + list.size() + " taxa. " + "If the XML file was set up in BEAUti, this probably means a taxon assignment needs to be set up in the taxonset panel."); // assume we are in BEAUti, back off for now return; diff --git a/src/beast/evolution/tree/Tree.java b/src/beast/evolution/tree/Tree.java index 7bd4715..964955d 100644 --- a/src/beast/evolution/tree/Tree.java +++ b/src/beast/evolution/tree/Tree.java @@ -60,7 +60,7 @@ public class Tree extends StateNode implements TreeInterface { * array of taxa names for the nodes in the tree * such that m_sTaxaNames[node.getNr()] == node.getID()* */ - String[] m_sTaxaNames = null; + protected String[] m_sTaxaNames = null; /** * Trait set which specifies leaf node times. @@ -111,8 +111,11 @@ public class Tree extends StateNode implements TreeInterface { // ensure all nodes have their taxon names set up String [] taxa = getTaxaNames(); for (int i = 0; i < getNodeCount() && i < taxa.length; i++) { - if (taxa[i] != null) - m_nodes[i].setID(taxa[i]); + if( taxa[i] != null ) { + if( m_nodes[i].getID() == null ) { + m_nodes[i].setID(taxa[i]); + } + } } } @@ -332,27 +335,32 @@ public class Tree extends StateNode implements TreeInterface { */ public String [] getTaxaNames() { if (m_sTaxaNames == null || (m_sTaxaNames.length == 1 && m_sTaxaNames[0] == null) || m_sTaxaNames.length == 0) { - final TaxonSet taxonSet = m_taxonset.get(); - if (taxonSet != null) { - final List<String> txs = taxonSet.asStringList(); - m_sTaxaNames = txs.toArray(new String[txs.size()]); - } else { - m_sTaxaNames = new String[getNodeCount()]; - collectTaxaNames(getRoot()); - List<String> taxaNames = new ArrayList<>(); - for (String name : m_sTaxaNames) { - if (name != null) { - taxaNames.add(name); - } - } - m_sTaxaNames = taxaNames.toArray(new String[]{}); - + // take taxa from tree if one exists + if( root != null ) { + m_sTaxaNames = new String[getNodeCount()]; + collectTaxaNames(getRoot()); + List<String> taxaNames = new ArrayList<>(); + for (String name : m_sTaxaNames) { + if (name != null) { + taxaNames.add(name); + } + } + m_sTaxaNames = taxaNames.toArray(new String[]{}); + } else { + // no tree? use taxon set. + final TaxonSet taxonSet = m_taxonset.get(); + if (taxonSet != null) { + final List<String> txs = taxonSet.asStringList(); + m_sTaxaNames = txs.toArray(new String[txs.size()]); + } else { + Log.err("No taxa specified"); + } } } // sanity check if (m_sTaxaNames.length == 1 && m_sTaxaNames[0] == null) { - Log.warning.println("WARNING: tree interrogated for taxa, but the tree was not initialised properly. To fix this, specify the taxonset input"); + Log.warning("WARNING: tree interrogated for taxa, but the tree was not initialised properly. To fix this, specify the taxonset input"); } return m_sTaxaNames; } @@ -948,7 +956,10 @@ public class Tree extends StateNode implements TreeInterface { } m_nodes = tmp; nodeCount--; - leafNodeCount--; + if (i < leafNodeCount) + leafNodeCount--; + else + internalNodeCount--; } /** @@ -962,7 +973,10 @@ public class Tree extends StateNode implements TreeInterface { newNode.setNr(nodeCount); m_nodes = tmp; nodeCount++; - leafNodeCount++; + if (newNode.getChildCount() > 0) + internalNodeCount++; + else + leafNodeCount++; } public int getDirectAncestorNodeCount() { diff --git a/src/beast/evolution/tree/TreeWithMetaDataLogger.java b/src/beast/evolution/tree/TreeWithMetaDataLogger.java index 1a00e0e..74bc86b 100644 --- a/src/beast/evolution/tree/TreeWithMetaDataLogger.java +++ b/src/beast/evolution/tree/TreeWithMetaDataLogger.java @@ -14,6 +14,7 @@ import beast.core.Input.Validate; import beast.core.Loggable; import beast.core.StateNode; import beast.core.parameter.Parameter; +import beast.core.parameter.RealParameter; import beast.evolution.branchratemodel.BranchRateModel; @Description("Logs tree annotated with metadata and/or rates") @@ -23,7 +24,7 @@ public class TreeWithMetaDataLogger extends BEASTObject implements Loggable { final public Input<List<Function>> parameterInput = new Input<>("metadata", "meta data to be logged with the tree nodes",new ArrayList<>()); final public Input<BranchRateModel.Base> clockModelInput = new Input<>("branchratemodel", "rate to be logged with branches of the tree"); final public Input<Boolean> substitutionsInput = new Input<>("substitutions", "report branch lengths as substitutions (branch length times clock rate for the branch)", false); - final public Input<Integer> decimalPlacesInput = new Input<>("dp", "the number of decimal places to use writing branch lengths and rates, use -1 for full precision (default = full precision)", -1); + final public Input<Integer> decimalPlacesInput = new Input<>("dp", "the number of decimal places to use writing branch lengths, rates and real-valued metadata, use -1 for full precision (default = full precision)", -1); boolean someMetaDataNeedsLogging; @@ -33,6 +34,15 @@ public class TreeWithMetaDataLogger extends BEASTObject implements Loggable { @Override public void initAndValidate() { + int dp = decimalPlacesInput.get(); + if (dp < 0) { + df = null; + } else { + // just new DecimalFormat("#.######") (with dp time '#' after the decimal) + df = new DecimalFormat("#."+new String(new char[dp]).replace('\0', '#')); + df.setRoundingMode(RoundingMode.HALF_UP); + } + if (parameterInput.get().size() == 0 && clockModelInput.get() == null) { someMetaDataNeedsLogging = false; return; @@ -43,16 +53,6 @@ public class TreeWithMetaDataLogger extends BEASTObject implements Loggable { if (clockModelInput.get() != null) { substitutions = substitutionsInput.get(); } - - int dp = decimalPlacesInput.get(); - - if (dp < 0) { - df = null; - } else { - // just new DecimalFormat("#.######") (with dp time '#' after the decimal) - df = new DecimalFormat("#."+new String(new char[dp]).replace('\0', '#')); - df.setRoundingMode(RoundingMode.HALF_UP); - } } @Override @@ -120,14 +120,24 @@ public class TreeWithMetaDataLogger extends BEASTObject implements Loggable { if (dim > 1) { buf.append('{'); for (int i = 0; i < dim; i++) { - buf.append(p.getMatrixValue(node.labelNr, i)); + if (metadata instanceof RealParameter) { + RealParameter rp = (RealParameter) metadata; + appendDouble(buf, rp.getMatrixValue(node.labelNr, i)); + } else { + buf.append(p.getMatrixValue(node.labelNr, i)); + } if (i < dim - 1) { buf.append(','); } } buf.append('}'); } else { - buf.append(metadata.getArrayValue(node.labelNr)); + if (metadata instanceof RealParameter) { + RealParameter rp = (RealParameter) metadata; + appendDouble(buf, rp.getArrayValue(node.labelNr)); + } else { + buf.append(metadata.getArrayValue(node.labelNr)); + } } } else { buf.append(metadata.getArrayValue(node.labelNr)); diff --git a/src/beast/util/AddOnManager.java b/src/beast/util/AddOnManager.java index 05f55a9..ce326dc 100644 --- a/src/beast/util/AddOnManager.java +++ b/src/beast/util/AddOnManager.java @@ -846,69 +846,79 @@ public class AddOnManager { checkInstalledDependencies(packages); for (String jarDirName : getBeastDirectories()) { - File versionFile = new File(jarDirName + "/version.xml"); - String packageNameAndVersion = null; - if (versionFile.exists()) { - try { - // print name and version of package - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - Document doc = factory.newDocumentBuilder().parse(versionFile); - Element addon = doc.getDocumentElement(); - packageNameAndVersion = addon.getAttribute("name") + " v" + addon.getAttribute("version"); - Log.warning.println("Loading package " + packageNameAndVersion); - } catch (Exception e) { - // too bad, won't print out any info + try { + File versionFile = new File(jarDirName + "/version.xml"); + String packageNameAndVersion = null; + if (versionFile.exists()) { + try { + // print name and version of package + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + Document doc = factory.newDocumentBuilder().parse(versionFile); + Element addon = doc.getDocumentElement(); + packageNameAndVersion = addon.getAttribute("name") + " v" + addon.getAttribute("version"); + Log.warning.println("Loading package " + packageNameAndVersion); + } catch (Exception e) { + // too bad, won't print out any info + + // File is called version.xml, but is not a Beast2 version file + // Log.debug.print("Skipping "+jarDirName+" (not a Beast2 package)"); + } } - } - File jarDir = new File(jarDirName + "/lib"); - if (!jarDir.exists()) { - jarDir = new File(jarDirName + "\\lib"); - } - if (jarDir.exists() && jarDir.isDirectory()) { - for (String fileName : jarDir.list()) { - if (fileName.endsWith(".jar")) { - Log.debug.print("Probing: " + fileName + " "); - // check that we are not reload existing classes - String loadedClass = null; - try { - JarInputStream jarFile = new JarInputStream - (new FileInputStream(jarDir.getAbsolutePath() + "/" + fileName)); - JarEntry jarEntry; - - while (loadedClass == null) { - jarEntry = jarFile.getNextJarEntry(); - if (jarEntry == null) { - break; - } - if ((jarEntry.getName().endsWith(".class"))) { - String className = jarEntry.getName().replaceAll("/", "\\."); - className = className.substring(0, className.lastIndexOf('.')); - try { - /*Object o =*/ Class.forName(className); - loadedClass = className; - } catch (Exception e) { - // TODO: handle exception + File jarDir = new File(jarDirName + "/lib"); + if (!jarDir.exists()) { + jarDir = new File(jarDirName + "\\lib"); + } + if (jarDir.exists() && jarDir.isDirectory()) { + for (String fileName : jarDir.list()) { + if (fileName.endsWith(".jar")) { + Log.debug.print("Probing: " + fileName + " "); + // check that we are not reload existing classes + String loadedClass = null; + try { + JarInputStream jarFile = new JarInputStream + (new FileInputStream(jarDir.getAbsolutePath() + "/" + fileName)); + JarEntry jarEntry; + + while (loadedClass == null) { + jarEntry = jarFile.getNextJarEntry(); + if (jarEntry == null) { + break; } - if (loadedClass == null && packageNameAndVersion != null) { - classToPackageMap.put(className, packageNameAndVersion); + if ((jarEntry.getName().endsWith(".class"))) { + String className = jarEntry.getName().replaceAll("/", "\\."); + className = className.substring(0, className.lastIndexOf('.')); + try { + /*Object o =*/ + Class.forName(className); + loadedClass = className; + } catch (Exception e) { + // TODO: handle exception + } + if (loadedClass == null && packageNameAndVersion != null) { + classToPackageMap.put(className, packageNameAndVersion); + } } } + jarFile.close(); + } catch (Exception e) { + e.printStackTrace(); } - jarFile.close(); - } catch (Exception e) { - e.printStackTrace(); - } - @SuppressWarnings("deprecation") - URL url = new File(jarDir.getAbsolutePath() + "/" + fileName).toURL(); - if (loadedClass == null) { - addURL(url); - } else { - Log.debug.println("Skip loading " + url + ": contains class " + loadedClass + " that is already loaded"); + @SuppressWarnings("deprecation") + URL url = new File(jarDir.getAbsolutePath() + "/" + fileName).toURL(); + if (loadedClass == null) { + addURL(url); + } else { + Log.debug.println("Skip loading " + url + ": contains class " + loadedClass + " that is already loaded"); + } } } } + } catch (Exception e) { + // File exists, but cannot open the file for some reason + Log.debug.println("Skipping "+jarDirName+"/version.xml (unable to open file"); + Log.warning.println("Skipping "+jarDirName+"/version.xml (unable to open file"); } } externalJarsLoaded = true; diff --git a/src/beast/util/NexusParser.java b/src/beast/util/NexusParser.java index dbf9a79..75e13f1 100644 --- a/src/beast/util/NexusParser.java +++ b/src/beast/util/NexusParser.java @@ -19,6 +19,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import beast.core.BEASTInterface; +import beast.core.parameter.RealParameter; import beast.core.util.Log; import beast.evolution.alignment.Alignment; import beast.evolution.alignment.FilteredAlignment; @@ -844,11 +845,20 @@ public class NexusParser { // next get the calibration str0 = strs[strs.length - 1].trim(); String [] strs3 = str0.split("[\\(,\\)]"); + RealParameter [] param = new RealParameter[strs3.length]; + for (int i = 1; i < strs3.length; i++) { + try { + param[i] = new RealParameter(strs3[i]); + param[i].setID("param." + i); + } catch (Exception e) { + // ignore parsing errors + } + } ParametricDistribution distr = null; switch (strs3[0]) { case "normal": distr = new Normal(); - distr.initByName("mean", strs3[1], "sigma", strs3[2]); + distr.initByName("mean", param[1], "sigma", param[2]); distr.setID("Normal.0"); break; case "uniform": @@ -858,33 +868,33 @@ public class NexusParser { break; case "fixed": // uniform with lower == upper - distr = new Uniform(); - distr.initByName("lower", strs3[1], "upper", strs3[1]); - distr.setID("Uniform.0"); + distr = new Normal(); + distr.initByName("mean", param[1], "sigma", "+Infinity"); + distr.setID("Normal.0"); break; case "offsetlognormal": distr = new LogNormalDistributionModel(); - distr.initByName("offset", strs3[1], "M", strs3[2], "S", strs3[3], "meanInRealSpace", true); - distr.setID("LogNormal.0"); + distr.initByName("offset", strs3[1], "M", param[2], "S", param[3], "meanInRealSpace", true); + distr.setID("LogNormalDistributionModel.0"); break; case "lognormal": distr = new LogNormalDistributionModel(); - distr.initByName("M", strs3[1], "S", strs3[2], "meanInRealSpace", true); - distr.setID("LogNormal.0"); + distr.initByName("M", param[1], "S", param[2], "meanInRealSpace", true); + distr.setID("LogNormalDistributionModel.0"); break; case "offsetexponential": distr = new Exponential(); - distr.initByName("offset", strs3[1], "mean", strs3[2]); + distr.initByName("offset", strs3[1], "mean", param[2]); distr.setID("Exponential.0"); break; case "gamma": distr = new Gamma(); - distr.initByName("alpha", strs3[1], "beta", strs3[2]); + distr.initByName("alpha", param[1], "beta", param[2]); distr.setID("Gamma.0"); break; case "offsetgamma": distr = new Gamma(); - distr.initByName("offset", strs3[1], "alpha", strs3[2], "beta", strs3[3]); + distr.initByName("offset", strs3[1], "alpha", param[2], "beta", param[3]); distr.setID("Gamma.0"); break; default: diff --git a/src/beast/util/TreeParser.java b/src/beast/util/TreeParser.java index b46423e..8b496e7 100644 --- a/src/beast/util/TreeParser.java +++ b/src/beast/util/TreeParser.java @@ -164,7 +164,8 @@ public class TreeParser extends Tree implements StateNodeInitialiser { } super.initAndValidate(); - + m_sTaxaNames = null; + if (sortNodesAlphabetically) { // correct for node ordering: ensure order is alphabetical for (int i = 0; i < getNodeCount() && i < labels.size(); i++) { @@ -468,18 +469,21 @@ public class TreeParser extends Tree implements StateNodeInitialiser { } node.setMetaData(key, stringValue); } else if (attribctx.attribValue().vector() != null) { - try { - String value = attribctx.attribValue().vector().getText(); - String str = value.substring(1, value.length() - 1); - String [] strs = str.split(","); - Double [] values = new Double[strs.length]; - for (int j = 0; j < strs.length; j++) { - values[j] = Double.parseDouble(strs[j]); - } - node.setMetaData(key, values); - } catch (Exception e) { - // ignore parsing errors - } + try { + + List<NewickParser.AttribValueContext> elementContexts = attribctx.attribValue().vector().attribValue(); + + Double[] values = new Double[elementContexts.size()]; + for (int i = 0; i < elementContexts.size(); i++) + values[i] = Double.parseDouble(elementContexts.get(i).getText()); + + node.setMetaData(key, values); + + } catch (NumberFormatException ex) { + throw new ParseCancellationException("Encountered vector-valued metadata entry with " + + "one or more non-numeric elements."); + } + } } } @@ -502,10 +506,6 @@ public class TreeParser extends Tree implements StateNodeInitialiser { || postCtx.label().number().INT() == null) integerLeafLabels = false; - // RRB: next line is for debugging only? - @SuppressWarnings("unused") - String postText = postCtx.getText(); - // Treat labels as node numbers in certain situations if (!isLabelledNewickInput.get() && postCtx.label().number() != null diff --git a/src/beast/util/treeparser/Newick.g4 b/src/beast/util/treeparser/Newick.g4 index e22a143..708c2c5 100644 --- a/src/beast/util/treeparser/Newick.g4 +++ b/src/beast/util/treeparser/Newick.g4 @@ -16,14 +16,15 @@ attrib: attribKey=STRING '=' attribValue ; attribValue: number | STRING | vector; -number: INT | FLOAT ; +number: INT | FLOAT | FLOAT_SCI; vector: '{' attribValue (',' attribValue)* '}' ; // Lexer rules: -FLOAT : '-'? NNINT ('.' D*) ([eE] '-'? D+)? ; +FLOAT_SCI: '-'? ((NNINT? ('.' D+)) | (NNINT ('.' D+)?)) ([eE] '-'? D+); +FLOAT : '-'? ((NNINT? ('.' D+)) | (NNINT ('.' D*))); INT : '-'? NNINT; fragment NNINT : '0' | NZD D* ; fragment NZD : [1-9] ; diff --git a/src/beast/util/treeparser/NewickBaseVisitor.java b/src/beast/util/treeparser/NewickBaseVisitor.java index 4503959..2c895e2 100644 --- a/src/beast/util/treeparser/NewickBaseVisitor.java +++ b/src/beast/util/treeparser/NewickBaseVisitor.java @@ -1,4 +1,4 @@ -// Generated from Newick.g4 by ANTLR 4.5.1 +// Generated from /home/tvaughan/code/beast_and_friends/beast2/src/beast/util/treeparser/Newick.g4 by ANTLR 4.5.3 package beast.util.treeparser; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; diff --git a/src/beast/util/treeparser/NewickLexer.java b/src/beast/util/treeparser/NewickLexer.java index de1ed93..5bf9938 100644 --- a/src/beast/util/treeparser/NewickLexer.java +++ b/src/beast/util/treeparser/NewickLexer.java @@ -1,4 +1,4 @@ -// Generated from Newick.g4 by ANTLR 4.5.1 +// Generated from /home/tvaughan/code/beast_and_friends/beast2/src/beast/util/treeparser/Newick.g4 by ANTLR 4.5.3 package beast.util.treeparser; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.CharStream; @@ -11,21 +11,21 @@ import org.antlr.v4.runtime.misc.*; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class NewickLexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION); } + static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); } protected static final DFA[] _decisionToDFA; protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, FLOAT=11, INT=12, STRING=13, WHITESPACE=14; + T__9=10, FLOAT_SCI=11, FLOAT=12, INT=13, STRING=14, WHITESPACE=15; public static String[] modeNames = { "DEFAULT_MODE" }; public static final String[] ruleNames = { "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", - "T__9", "FLOAT", "INT", "NNINT", "NZD", "D", "STRING", "WHITESPACE" + "T__9", "FLOAT_SCI", "FLOAT", "INT", "NNINT", "NZD", "D", "STRING", "WHITESPACE" }; private static final String[] _LITERAL_NAMES = { @@ -33,8 +33,8 @@ public class NewickLexer extends Lexer { "'}'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, "FLOAT", - "INT", "STRING", "WHITESPACE" + null, null, null, null, null, null, null, null, null, null, null, "FLOAT_SCI", + "FLOAT", "INT", "STRING", "WHITESPACE" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -91,40 +91,56 @@ public class NewickLexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\20\u0081\b\1\4\2"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\21\u00a3\b\1\4\2"+ "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ - "\t\22\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\7\3\b\3\b\3\t"+ - "\3\t\3\n\3\n\3\13\3\13\3\f\5\f<\n\f\3\f\3\f\3\f\7\fA\n\f\f\f\16\fD\13"+ - "\f\3\f\3\f\5\fH\n\f\3\f\6\fK\n\f\r\f\16\fL\5\fO\n\f\3\r\5\rR\n\r\3\r\3"+ - "\r\3\16\3\16\3\16\7\16Y\n\16\f\16\16\16\\\13\16\5\16^\n\16\3\17\3\17\3"+ - "\20\3\20\3\21\6\21e\n\21\r\21\16\21f\3\21\3\21\7\21k\n\21\f\21\16\21n"+ - "\13\21\3\21\3\21\3\21\7\21s\n\21\f\21\16\21v\13\21\3\21\5\21y\n\21\3\22"+ - "\6\22|\n\22\r\22\16\22}\3\22\3\22\4lt\2\23\3\3\5\4\7\5\t\6\13\7\r\b\17"+ - "\t\21\n\23\13\25\f\27\r\31\16\33\2\35\2\37\2!\17#\20\3\2\7\4\2GGgg\3\2"+ - "\63;\3\2\62;\n\2%%\'(,-/;C\\aac|~~\5\2\13\f\17\17\"\"\u008b\2\3\3\2\2"+ - "\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3"+ - "\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2"+ - "\2\2!\3\2\2\2\2#\3\2\2\2\3%\3\2\2\2\5\'\3\2\2\2\7)\3\2\2\2\t+\3\2\2\2"+ - "\13-\3\2\2\2\r/\3\2\2\2\17\62\3\2\2\2\21\64\3\2\2\2\23\66\3\2\2\2\258"+ - "\3\2\2\2\27;\3\2\2\2\31Q\3\2\2\2\33]\3\2\2\2\35_\3\2\2\2\37a\3\2\2\2!"+ - "x\3\2\2\2#{\3\2\2\2%&\7=\2\2&\4\3\2\2\2\'(\7*\2\2(\6\3\2\2\2)*\7.\2\2"+ - "*\b\3\2\2\2+,\7+\2\2,\n\3\2\2\2-.\7<\2\2.\f\3\2\2\2/\60\7]\2\2\60\61\7"+ - "(\2\2\61\16\3\2\2\2\62\63\7_\2\2\63\20\3\2\2\2\64\65\7?\2\2\65\22\3\2"+ - "\2\2\66\67\7}\2\2\67\24\3\2\2\289\7\177\2\29\26\3\2\2\2:<\7/\2\2;:\3\2"+ - "\2\2;<\3\2\2\2<=\3\2\2\2=>\5\33\16\2>B\7\60\2\2?A\5\37\20\2@?\3\2\2\2"+ - "AD\3\2\2\2B@\3\2\2\2BC\3\2\2\2CN\3\2\2\2DB\3\2\2\2EG\t\2\2\2FH\7/\2\2"+ - "GF\3\2\2\2GH\3\2\2\2HJ\3\2\2\2IK\5\37\20\2JI\3\2\2\2KL\3\2\2\2LJ\3\2\2"+ - "\2LM\3\2\2\2MO\3\2\2\2NE\3\2\2\2NO\3\2\2\2O\30\3\2\2\2PR\7/\2\2QP\3\2"+ - "\2\2QR\3\2\2\2RS\3\2\2\2ST\5\33\16\2T\32\3\2\2\2U^\7\62\2\2VZ\5\35\17"+ - "\2WY\5\37\20\2XW\3\2\2\2Y\\\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[^\3\2\2\2\\Z\3"+ - "\2\2\2]U\3\2\2\2]V\3\2\2\2^\34\3\2\2\2_`\t\3\2\2`\36\3\2\2\2ab\t\4\2\2"+ - "b \3\2\2\2ce\t\5\2\2dc\3\2\2\2ef\3\2\2\2fd\3\2\2\2fg\3\2\2\2gy\3\2\2\2"+ - "hl\7$\2\2ik\13\2\2\2ji\3\2\2\2kn\3\2\2\2lm\3\2\2\2lj\3\2\2\2mo\3\2\2\2"+ - "nl\3\2\2\2oy\7$\2\2pt\7)\2\2qs\13\2\2\2rq\3\2\2\2sv\3\2\2\2tu\3\2\2\2"+ - "tr\3\2\2\2uw\3\2\2\2vt\3\2\2\2wy\7)\2\2xd\3\2\2\2xh\3\2\2\2xp\3\2\2\2"+ - "y\"\3\2\2\2z|\t\6\2\2{z\3\2\2\2|}\3\2\2\2}{\3\2\2\2}~\3\2\2\2~\177\3\2"+ - "\2\2\177\u0080\b\22\2\2\u0080$\3\2\2\2\20\2;BGLNQZ]fltx}\3\b\2\2"; + "\t\22\4\23\t\23\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\7\3"+ + "\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\5\f>\n\f\3\f\5\fA\n\f\3\f\3\f\6\f"+ + "E\n\f\r\f\16\fF\3\f\3\f\3\f\6\fL\n\f\r\f\16\fM\5\fP\n\f\5\fR\n\f\3\f\3"+ + "\f\5\fV\n\f\3\f\6\fY\n\f\r\f\16\fZ\3\r\5\r^\n\r\3\r\5\ra\n\r\3\r\3\r\6"+ + "\re\n\r\r\r\16\rf\3\r\3\r\3\r\7\rl\n\r\f\r\16\ro\13\r\5\rq\n\r\3\16\5"+ + "\16t\n\16\3\16\3\16\3\17\3\17\3\17\7\17{\n\17\f\17\16\17~\13\17\5\17\u0080"+ + "\n\17\3\20\3\20\3\21\3\21\3\22\6\22\u0087\n\22\r\22\16\22\u0088\3\22\3"+ + "\22\7\22\u008d\n\22\f\22\16\22\u0090\13\22\3\22\3\22\3\22\7\22\u0095\n"+ + "\22\f\22\16\22\u0098\13\22\3\22\5\22\u009b\n\22\3\23\6\23\u009e\n\23\r"+ + "\23\16\23\u009f\3\23\3\23\4\u008e\u0096\2\24\3\3\5\4\7\5\t\6\13\7\r\b"+ + "\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\2\37\2!\2#\20%\21\3\2\7\4\2"+ + "GGgg\3\2\63;\3\2\62;\n\2%%\'(,-/;C\\aac|~~\5\2\13\f\17\17\"\"\u00b5\2"+ + "\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2"+ + "\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2"+ + "\31\3\2\2\2\2\33\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\3\'\3\2\2\2\5)\3\2\2\2"+ + "\7+\3\2\2\2\t-\3\2\2\2\13/\3\2\2\2\r\61\3\2\2\2\17\64\3\2\2\2\21\66\3"+ + "\2\2\2\238\3\2\2\2\25:\3\2\2\2\27=\3\2\2\2\31]\3\2\2\2\33s\3\2\2\2\35"+ + "\177\3\2\2\2\37\u0081\3\2\2\2!\u0083\3\2\2\2#\u009a\3\2\2\2%\u009d\3\2"+ + "\2\2\'(\7=\2\2(\4\3\2\2\2)*\7*\2\2*\6\3\2\2\2+,\7.\2\2,\b\3\2\2\2-.\7"+ + "+\2\2.\n\3\2\2\2/\60\7<\2\2\60\f\3\2\2\2\61\62\7]\2\2\62\63\7(\2\2\63"+ + "\16\3\2\2\2\64\65\7_\2\2\65\20\3\2\2\2\66\67\7?\2\2\67\22\3\2\2\289\7"+ + "}\2\29\24\3\2\2\2:;\7\177\2\2;\26\3\2\2\2<>\7/\2\2=<\3\2\2\2=>\3\2\2\2"+ + ">Q\3\2\2\2?A\5\35\17\2@?\3\2\2\2@A\3\2\2\2AB\3\2\2\2BD\7\60\2\2CE\5!\21"+ + "\2DC\3\2\2\2EF\3\2\2\2FD\3\2\2\2FG\3\2\2\2GR\3\2\2\2HO\5\35\17\2IK\7\60"+ + "\2\2JL\5!\21\2KJ\3\2\2\2LM\3\2\2\2MK\3\2\2\2MN\3\2\2\2NP\3\2\2\2OI\3\2"+ + "\2\2OP\3\2\2\2PR\3\2\2\2Q@\3\2\2\2QH\3\2\2\2RS\3\2\2\2SU\t\2\2\2TV\7/"+ + "\2\2UT\3\2\2\2UV\3\2\2\2VX\3\2\2\2WY\5!\21\2XW\3\2\2\2YZ\3\2\2\2ZX\3\2"+ + "\2\2Z[\3\2\2\2[\30\3\2\2\2\\^\7/\2\2]\\\3\2\2\2]^\3\2\2\2^p\3\2\2\2_a"+ + "\5\35\17\2`_\3\2\2\2`a\3\2\2\2ab\3\2\2\2bd\7\60\2\2ce\5!\21\2dc\3\2\2"+ + "\2ef\3\2\2\2fd\3\2\2\2fg\3\2\2\2gq\3\2\2\2hi\5\35\17\2im\7\60\2\2jl\5"+ + "!\21\2kj\3\2\2\2lo\3\2\2\2mk\3\2\2\2mn\3\2\2\2nq\3\2\2\2om\3\2\2\2p`\3"+ + "\2\2\2ph\3\2\2\2q\32\3\2\2\2rt\7/\2\2sr\3\2\2\2st\3\2\2\2tu\3\2\2\2uv"+ + "\5\35\17\2v\34\3\2\2\2w\u0080\7\62\2\2x|\5\37\20\2y{\5!\21\2zy\3\2\2\2"+ + "{~\3\2\2\2|z\3\2\2\2|}\3\2\2\2}\u0080\3\2\2\2~|\3\2\2\2\177w\3\2\2\2\177"+ + "x\3\2\2\2\u0080\36\3\2\2\2\u0081\u0082\t\3\2\2\u0082 \3\2\2\2\u0083\u0084"+ + "\t\4\2\2\u0084\"\3\2\2\2\u0085\u0087\t\5\2\2\u0086\u0085\3\2\2\2\u0087"+ + "\u0088\3\2\2\2\u0088\u0086\3\2\2\2\u0088\u0089\3\2\2\2\u0089\u009b\3\2"+ + "\2\2\u008a\u008e\7$\2\2\u008b\u008d\13\2\2\2\u008c\u008b\3\2\2\2\u008d"+ + "\u0090\3\2\2\2\u008e\u008f\3\2\2\2\u008e\u008c\3\2\2\2\u008f\u0091\3\2"+ + "\2\2\u0090\u008e\3\2\2\2\u0091\u009b\7$\2\2\u0092\u0096\7)\2\2\u0093\u0095"+ + "\13\2\2\2\u0094\u0093\3\2\2\2\u0095\u0098\3\2\2\2\u0096\u0097\3\2\2\2"+ + "\u0096\u0094\3\2\2\2\u0097\u0099\3\2\2\2\u0098\u0096\3\2\2\2\u0099\u009b"+ + "\7)\2\2\u009a\u0086\3\2\2\2\u009a\u008a\3\2\2\2\u009a\u0092\3\2\2\2\u009b"+ + "$\3\2\2\2\u009c\u009e\t\6\2\2\u009d\u009c\3\2\2\2\u009e\u009f\3\2\2\2"+ + "\u009f\u009d\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\u00a2"+ + "\b\23\2\2\u00a2&\3\2\2\2\30\2=@FMOQUZ]`fmps|\177\u0088\u008e\u0096\u009a"+ + "\u009f\3\b\2\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/beast/util/treeparser/NewickParser.java b/src/beast/util/treeparser/NewickParser.java index 6833af0..66d6eaa 100644 --- a/src/beast/util/treeparser/NewickParser.java +++ b/src/beast/util/treeparser/NewickParser.java @@ -1,4 +1,4 @@ -// Generated from Newick.g4 by ANTLR 4.5.1 +// Generated from /home/tvaughan/code/beast_and_friends/beast2/src/beast/util/treeparser/Newick.g4 by ANTLR 4.5.3 package beast.util.treeparser; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.DFA; @@ -11,14 +11,14 @@ import java.util.ArrayList; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class NewickParser extends Parser { - static { RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION); } + static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); } protected static final DFA[] _decisionToDFA; protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, FLOAT=11, INT=12, STRING=13, WHITESPACE=14; + T__9=10, FLOAT_SCI=11, FLOAT=12, INT=13, STRING=14, WHITESPACE=15; public static final int RULE_tree = 0, RULE_node = 1, RULE_post = 2, RULE_label = 3, RULE_meta = 4, RULE_attrib = 5, RULE_attribValue = 6, RULE_number = 7, RULE_vector = 8; @@ -32,8 +32,8 @@ public class NewickParser extends Parser { "'}'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, "FLOAT", - "INT", "STRING", "WHITESPACE" + null, null, null, null, null, null, null, null, null, null, null, "FLOAT_SCI", + "FLOAT", "INT", "STRING", "WHITESPACE" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -236,7 +236,7 @@ public class NewickParser extends Parser { { setState(40); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FLOAT) | (1L << INT) | (1L << STRING))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FLOAT_SCI) | (1L << FLOAT) | (1L << INT) | (1L << STRING))) != 0)) { { setState(39); label(); @@ -298,6 +298,7 @@ public class NewickParser extends Parser { try { setState(51); switch (_input.LA(1)) { + case FLOAT_SCI: case FLOAT: case INT: enterOuterAlt(_localctx, 1); @@ -455,6 +456,7 @@ public class NewickParser extends Parser { try { setState(71); switch (_input.LA(1)) { + case FLOAT_SCI: case FLOAT: case INT: enterOuterAlt(_localctx, 1); @@ -495,6 +497,7 @@ public class NewickParser extends Parser { public static class NumberContext extends ParserRuleContext { public TerminalNode INT() { return getToken(NewickParser.INT, 0); } public TerminalNode FLOAT() { return getToken(NewickParser.FLOAT, 0); } + public TerminalNode FLOAT_SCI() { return getToken(NewickParser.FLOAT_SCI, 0); } public NumberContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -515,7 +518,7 @@ public class NewickParser extends Parser { { setState(73); _la = _input.LA(1); - if ( !(_la==FLOAT || _la==INT) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FLOAT_SCI) | (1L << FLOAT) | (1L << INT))) != 0)) ) { _errHandler.recoverInline(this); } else { consume(); @@ -594,13 +597,13 @@ public class NewickParser extends Parser { } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\20Y\4\2\t\2\4\3\t"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\21Y\4\2\t\2\4\3\t"+ "\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\3\2\3\2\5\2"+ "\27\n\2\3\2\3\2\3\3\3\3\3\3\3\3\7\3\37\n\3\f\3\16\3\"\13\3\3\3\3\3\5\3"+ "&\n\3\3\3\3\3\3\4\5\4+\n\4\3\4\5\4.\n\4\3\4\3\4\5\4\62\n\4\3\5\3\5\5\5"+ "\66\n\5\3\6\3\6\3\6\3\6\7\6<\n\6\f\6\16\6?\13\6\3\6\3\6\3\7\3\7\3\7\3"+ "\7\3\b\3\b\3\b\5\bJ\n\b\3\t\3\t\3\n\3\n\3\n\3\n\7\nR\n\n\f\n\16\nU\13"+ - "\n\3\n\3\n\3\n\2\2\13\2\4\6\b\n\f\16\20\22\2\3\3\2\r\16Z\2\24\3\2\2\2"+ + "\n\3\n\3\n\3\n\2\2\13\2\4\6\b\n\f\16\20\22\2\3\3\2\r\17Z\2\24\3\2\2\2"+ "\4%\3\2\2\2\6*\3\2\2\2\b\65\3\2\2\2\n\67\3\2\2\2\fB\3\2\2\2\16I\3\2\2"+ "\2\20K\3\2\2\2\22M\3\2\2\2\24\26\5\4\3\2\25\27\7\3\2\2\26\25\3\2\2\2\26"+ "\27\3\2\2\2\27\30\3\2\2\2\30\31\7\2\2\3\31\3\3\2\2\2\32\33\7\4\2\2\33"+ @@ -609,10 +612,10 @@ public class NewickParser extends Parser { "%&\3\2\2\2&\'\3\2\2\2\'(\5\6\4\2(\5\3\2\2\2)+\5\b\5\2*)\3\2\2\2*+\3\2"+ "\2\2+-\3\2\2\2,.\5\n\6\2-,\3\2\2\2-.\3\2\2\2.\61\3\2\2\2/\60\7\7\2\2\60"+ "\62\5\20\t\2\61/\3\2\2\2\61\62\3\2\2\2\62\7\3\2\2\2\63\66\5\20\t\2\64"+ - "\66\7\17\2\2\65\63\3\2\2\2\65\64\3\2\2\2\66\t\3\2\2\2\678\7\b\2\28=\5"+ + "\66\7\20\2\2\65\63\3\2\2\2\65\64\3\2\2\2\66\t\3\2\2\2\678\7\b\2\28=\5"+ "\f\7\29:\7\5\2\2:<\5\f\7\2;9\3\2\2\2<?\3\2\2\2=;\3\2\2\2=>\3\2\2\2>@\3"+ - "\2\2\2?=\3\2\2\2@A\7\t\2\2A\13\3\2\2\2BC\7\17\2\2CD\7\n\2\2DE\5\16\b\2"+ - "E\r\3\2\2\2FJ\5\20\t\2GJ\7\17\2\2HJ\5\22\n\2IF\3\2\2\2IG\3\2\2\2IH\3\2"+ + "\2\2\2?=\3\2\2\2@A\7\t\2\2A\13\3\2\2\2BC\7\20\2\2CD\7\n\2\2DE\5\16\b\2"+ + "E\r\3\2\2\2FJ\5\20\t\2GJ\7\20\2\2HJ\5\22\n\2IF\3\2\2\2IG\3\2\2\2IH\3\2"+ "\2\2J\17\3\2\2\2KL\t\2\2\2L\21\3\2\2\2MN\7\13\2\2NS\5\16\b\2OP\7\5\2\2"+ "PR\5\16\b\2QO\3\2\2\2RU\3\2\2\2SQ\3\2\2\2ST\3\2\2\2TV\3\2\2\2US\3\2\2"+ "\2VW\7\f\2\2W\23\3\2\2\2\f\26 %*-\61\65=IS"; diff --git a/src/beast/util/treeparser/NewickVisitor.java b/src/beast/util/treeparser/NewickVisitor.java index 9041257..b4dbd8b 100644 --- a/src/beast/util/treeparser/NewickVisitor.java +++ b/src/beast/util/treeparser/NewickVisitor.java @@ -1,4 +1,4 @@ -// Generated from Newick.g4 by ANTLR 4.5.1 +// Generated from /home/tvaughan/code/beast_and_friends/beast2/src/beast/util/treeparser/Newick.g4 by ANTLR 4.5.3 package beast.util.treeparser; import org.antlr.v4.runtime.tree.ParseTreeVisitor; diff --git a/src/test/beast/evolution/alignment/FilteredAlignmentTest.java b/src/test/beast/evolution/alignment/FilteredAlignmentTest.java index d23b823..656ec6a 100644 --- a/src/test/beast/evolution/alignment/FilteredAlignmentTest.java +++ b/src/test/beast/evolution/alignment/FilteredAlignmentTest.java @@ -290,20 +290,68 @@ public class FilteredAlignmentTest extends TestCase { assertEquals(alignmentToString(data2,0), alignmentToString(data4, 0)); assertEquals(alignmentToString(data2,1), alignmentToString(data4, 1)); -} + } - String alignmentToString(Alignment data, int iTaxon) throws Exception { - int[] states = new int[data.getPatternCount()]; -// for (int i = 0; i < data.getSiteCount(); i++) { -// int iPattern = data.getPatternIndex(i); -// int[] sitePattern = data.getPattern(iPattern); -// states[i] = sitePattern[iTaxon]; -// } + + @Test + public void testReordered() throws Exception { + // make sure the order of sites is not affected by filtering + Alignment data = getAlignmentNoTInHuman(); + data.setID("data"); + + // second sequence not in alphabetical order + FilteredAlignment data2 = new FilteredAlignment(); + data2.initByName("data", data, "filter", "3:6:1"); + + System.out.println("human\t" + alignmentToString(data2, 0) + "\n1chimp\t" + + alignmentToString(data2, 1)); + + assertEquals(alignmentToString(data2,0), "AACC"); + assertEquals(alignmentToString(data2,1), "GTAC"); + + // first sequence not in alphabetical order + FilteredAlignment data3 = new FilteredAlignment(); + data3.initByName("data", data, "filter", "11:14:1"); - for (int i = 0; i < data.getPatternCount(); i++) { - int[] sitePattern = data.getPattern(i); + System.out.println("human\t" + alignmentToString(data3, 0) + "\n1chimp\t" + + alignmentToString(data3, 1)); + + assertEquals(alignmentToString(data3,0), "GGAA"); + assertEquals(alignmentToString(data3,1), "GTAC"); + + // first sequence not in alphabetical order, repeat site + FilteredAlignment data4 = new FilteredAlignment(); + data4.initByName("data", data, "filter", "3:16:4"); + + System.out.println("human\t" + alignmentToString(data4, 0) + "\n1chimp\t" + + alignmentToString(data4, 1)); + + assertEquals(alignmentToString(data4,0), "ACGA"); + assertEquals(alignmentToString(data4,1), "GGGG"); + + // first and second sequence not in alphabetical order + FilteredAlignment data5 = new FilteredAlignment(); + data5.initByName("data", data, "filter", "4:14:3"); + + System.out.println("human\t" + alignmentToString(data5, 0) + "\n1chimp\t" + + alignmentToString(data5, 1)); + + assertEquals(alignmentToString(data5,0), "ACGA"); + assertEquals(alignmentToString(data5,1), "TGCA"); + } + + String alignmentToString(Alignment data, int iTaxon) throws Exception { + int[] states = new int[data.getSiteCount()]; + for (int i = 0; i < data.getSiteCount(); i++) { + int iPattern = data.getPatternIndex(i); + int[] sitePattern = data.getPattern(iPattern); states[i] = sitePattern[iTaxon]; } + +// for (int i = 0; i < data.getPatternCount(); i++) { +// int[] sitePattern = data.getPattern(i); +// states[i] = sitePattern[iTaxon]; +// } return data.getDataType().state2string(states); } } diff --git a/src/test/beast/util/TreeParserTest.java b/src/test/beast/util/TreeParserTest.java index d9d883f..29795ad 100644 --- a/src/test/beast/util/TreeParserTest.java +++ b/src/test/beast/util/TreeParserTest.java @@ -4,6 +4,7 @@ import org.junit.Assert; import org.junit.Test; import beast.util.TreeParser; +import org.omg.CORBA.OBJ_ADAPTER; public class TreeParserTest { @@ -110,4 +111,17 @@ public class TreeParserTest { } + @Test + public void testVectorMetadata() throws Exception { + + String newick = "((A:1.0,B[&key={1,2,3}]:1.0):1.0,(C:1.0,D:1.0):1.0):0.0;"; + + boolean isLabeled = true; + + TreeParser treeParser = new TreeParser(newick, false, false, isLabeled, 1); + Assert.assertTrue((treeParser.getNode(1).getMetaData("key") instanceof Double[]) + && ((Double[])(treeParser.getNode(1).getMetaData("key"))).length == 3); + + } + } diff --git a/version.xml b/version.xml index 912afa0..6ee75a3 100644 --- a/version.xml +++ b/version.xml @@ -1 +1 @@ -<addon name='BEAST' version='2.4.2' url="https://github.com/CompEvol/beast2/releases/download/2.4.2pre/BEAST.v2.4.2.addon.zip"/> +<addon name='BEAST' version='2.4.4' url="https://github.com/CompEvol/beast2/releases/download/2.4.4/BEAST.v2.4.4.addon.zip"/> -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/beast2-mcmc.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
