/** * Create a tree from the given newick format * * @param taxaNames a list of taxa names to use, or null. If null then IsLabelledNewick will be * set to true * @param newick the newick of the tree * @param offset the offset to map node numbers in newick format to indices in taxaNames. so, * name(node with nodeNumber) = taxaNames[nodeNumber-offset] * @param adjustTipHeightsWhenMissingDateTraits true if tip heights should be adjusted to zero * @throws Exception */ public TreeParser( final List<String> taxaNames, final String newick, final int offset, final boolean adjustTipHeightsWhenMissingDateTraits) throws Exception { if (taxaNames == null) { isLabelledNewickInput.setValue(true, this); } else { m_taxonset.setValue(new TaxonSet(Taxon.createTaxonList(taxaNames)), this); } newickInput.setValue(newick, this); offsetInput.setValue(offset, this); adjustTipHeightsInput.setValue(adjustTipHeightsWhenMissingDateTraits, this); labels = taxaNames; initAndValidate(); }
/** Ensure the class behaves properly, even when inputs are not specified. */ @Override public void initAndValidate() throws Exception { boolean sortNodesAlphabetically = false; if (dataInput.get() != null) { labels = dataInput.get().getTaxaNames(); } else if (m_taxonset.get() != null) { if (labels == null) { labels = m_taxonset.get().asStringList(); } else { // else labels were set by TreeParser c'tor sortNodesAlphabetically = true; } } else { if (isLabelledNewickInput.get()) { if (m_initial.get() != null) { labels = m_initial.get().getTaxonset().asStringList(); } else { labels = new ArrayList<>(); createUnrecognizedTaxa = true; sortNodesAlphabetically = true; } } else { if (m_initial.get() != null) { // try to pick up taxa from initial tree final Tree tree = m_initial.get(); if (tree.m_taxonset.get() != null) { labels = tree.m_taxonset.get().asStringList(); } else { // m_sLabels = null; } } else { // m_sLabels = null; } } // m_bIsLabelledNewick = false; } final String newick = newickInput.get(); if (newick == null || newick.equals("")) { // can happen while initalising Beauti final Node dummy = new Node(); setRoot(dummy); } else { try { setRoot(parseNewick(newickInput.get())); } catch (ParseCancellationException e) { throw new RuntimeException( "TreeParser cannot make sense of the Newick string " + "provided. It gives the following clue:\n" + e.getMessage()); } } super.initAndValidate(); if (sortNodesAlphabetically) { // correct for node ordering: ensure order is alphabetical for (int i = 0; i < getNodeCount() && i < labels.size(); i++) { m_nodes[i].setID(labels.get(i)); } Node[] nodes = new Node[labels.size()]; System.arraycopy(m_nodes, 0, nodes, 0, labels.size()); Arrays.sort(nodes, (o1, o2) -> o1.getID().compareTo(o2.getID())); for (int i = 0; i < labels.size(); i++) { m_nodes[i] = nodes[i]; nodes[i].setNr(i); } } if (m_initial.get() != null) processTraits(m_initial.get().m_traitList.get()); else processTraits(m_traitList.get()); if (timeTraitSet != null) { adjustTreeNodeHeights(root); } else if (adjustTipHeightsInput.get()) { double treeLength = TreeUtils.getTreeLength(this, getRoot()); double extraTreeLength = 0.0; double maxTipHeight = 0.0; // all nodes should be at zero height if no date-trait is available for (int i = 0; i < getLeafNodeCount(); i++) { double height = getNode(i).getHeight(); if (maxTipHeight < height) { maxTipHeight = height; } extraTreeLength += height; getNode(i).setHeight(0); } double scaleFactor = (treeLength + extraTreeLength) / treeLength; final double SCALE_FACTOR_THRESHOLD = 0.001; // if the change in total tree length is more than 0.1% then give the user a warning! if (scaleFactor > 1.0 + SCALE_FACTOR_THRESHOLD) { DecimalFormat format = new DecimalFormat("#.##"); Log.info.println( "WARNING: Adjust tip heights attribute set to 'true' in " + getClass().getSimpleName()); Log.info.println( " has resulted in significant (>" + format.format(SCALE_FACTOR_THRESHOLD * 100.0) + "%) change in tree length."); Log.info.println( " Use " + adjustTipHeightsInput.getName() + "='false' to override this default."); Log.info.printf(" original max tip age = %8.3f\n", maxTipHeight); Log.info.printf(" new max tip age = %8.3f\n", 0.0); Log.info.printf(" original tree length = %8.3f\n", treeLength); Log.info.printf(" new tree length = %8.3f\n", treeLength + extraTreeLength); Log.info.printf(" TL scale factor = %8.3f\n", scaleFactor); } } if (m_taxonset.get() == null && labels != null && isLabelledNewickInput.get()) { m_taxonset.setValue(new TaxonSet(Taxon.createTaxonList(labels)), this); } initStateNodes(); } // init