/* * CladeSystem.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.app.treespace; import dr.evolution.tree.*; import dr.evolution.util.TaxonList; import java.util.*; /** * @author Andrew Rambaut * @version $Id$ */ public class CladeSystem { /** */ public CladeSystem() { } /** * adds all the clades in the tree */ public void add(Tree tree, boolean includeTips) { if (taxonList == null) { taxonList = tree; } // Recurse over the tree and add all the clades (or increment their // frequency if already present). The root clade is added too (for // annotation purposes). addClades(tree, tree.getRoot(), includeTips); } // // public Clade getClade(NodeRef node) { // return null; // } private BitSet addClades(Tree tree, NodeRef node, boolean includeTips) { BitSet bits = new BitSet(); if (tree.isExternal(node)) { int index = taxonList.getTaxonIndex(tree.getNodeTaxon(node).getId()); bits.set(index); if (includeTips) { addClade(bits, taxonList.getTaxon(index).getId()); } } else { for (int i = 0; i < tree.getChildCount(node); i++) { NodeRef node1 = tree.getChild(node, i); bits.or(addClades(tree, node1, includeTips)); } addClade(bits); } return bits; } private void addClade(BitSet bits) { addClade(bits, null); } private void addClade(BitSet bits, String label) { Clade clade = cladeMap.get(bits); if (clade == null) { clade = new Clade(bits); cladeMap.put(bits, clade); } clade.setCount(clade.getCount() + 1); clade.label = label; } /** * adds all the clades in the tree */ public void addCooccurances(Tree tree) { addCladeCooccurances(tree, tree.getRoot(), null); } private BitSet addCladeCooccurances(Tree tree, NodeRef node, Clade parent) { BitSet bits = getCladeBitset(tree, node); Clade clade = cladeMap.get(bits); if (!tree.isExternal(node)) { if (clade == null) { throw new IllegalArgumentException("Clade missing for cooccurance network"); } for (int i = 0; i < tree.getChildCount(node); i++) { bits.or(addCladeCooccurances(tree, tree.getChild(node, i), clade)); } } if (clade != null && parent != null) { if (clade.parents == null) { clade.parents = new HashMap<Clade, Integer>(); } Integer frequency = clade.parents.get(parent); if (frequency == null) { frequency = 1; } else { frequency += 1; } clade.parents.put(parent, frequency); if (parent.children == null) { parent.children = new HashMap<Clade, Integer>(); } frequency = parent.children.get(clade); if (frequency == null) { frequency = 1; } else { frequency += 1; } parent.children.put(clade, frequency); } return bits; } private BitSet getCladeBitset(Tree tree, NodeRef node) { BitSet bits = new BitSet(); if (tree.isExternal(node)) { int index = taxonList.getTaxonIndex(tree.getNodeTaxon(node).getId()); bits.set(index); } else { for (int i = 0; i < tree.getChildCount(node); i++) { bits.or(getCladeBitset(tree, tree.getChild(node, i))); } } return bits; } public Map<BitSet, Clade> getCladeMap() { return cladeMap; } public void normalizeClades(int totalTreesUsed) { int i = 0; for (Clade clade : cladeMap.values()) { if (clade.getCount() > totalTreesUsed) { throw new AssertionError("clade.getCount=(" + clade.getCount() + ") should be <= totalTreesUsed = (" + totalTreesUsed + ")"); } clade.setCredibility(((double) clade.getCount()) / (double) totalTreesUsed); clade.index = i; i++; } } public double getLogCladeCredibility(Tree tree, NodeRef node, BitSet bits) { double logCladeCredibility = 0.0; if (tree.isExternal(node)) { int index = taxonList.getTaxonIndex(tree.getNodeTaxon(node).getId()); bits.set(index); } else { BitSet bits2 = new BitSet(); for (int i = 0; i < tree.getChildCount(node); i++) { NodeRef node1 = tree.getChild(node, i); logCladeCredibility += getLogCladeCredibility(tree, node1, bits2); } logCladeCredibility += Math.log(getCladeCredibility(bits2)); if (bits != null) { bits.or(bits2); } } return logCladeCredibility; } private double getCladeCredibility(BitSet bits) { Clade clade = cladeMap.get(bits); if (clade == null) { return 0.0; } return clade.getCredibility(); } public BitSet removeClades(Tree tree, NodeRef node, boolean includeTips) { BitSet bits = new BitSet(); if (tree.isExternal(node)) { int index = taxonList.getTaxonIndex(tree.getNodeTaxon(node).getId()); bits.set(index); if (includeTips) { removeClade(bits); } } else { for (int i = 0; i < tree.getChildCount(node); i++) { NodeRef node1 = tree.getChild(node, i); bits.or(removeClades(tree, node1, includeTips)); } removeClade(bits); } return bits; } private void removeClade(BitSet bits) { Clade clade = cladeMap.get(bits); if (clade != null) { clade.setCount(clade.getCount() - 1); } } public List<Clade> getClades() { return new ArrayList<Clade>(cladeMap.values()); } class Clade { public Clade(BitSet bits) { this.bits = bits; count = 0; credibility = 0.0; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public double getCredibility() { return credibility; } public void setCredibility(double credibility) { this.credibility = credibility; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Clade clade = (Clade) o; return !(bits != null ? !bits.equals(clade.bits) : clade.bits != null); } public int hashCode() { return (bits != null ? bits.hashCode() : 0); } public String toString() { return "clade " + bits.toString(); } int count; double credibility; BitSet bits; int index; String label; double height; float x, y; Map<Clade, Integer> children; Map<Clade, Integer> parents; } // // Private stuff // TaxonList taxonList = null; Map<BitSet, Clade> cladeMap = new HashMap<BitSet, Clade>(); Tree targetTree; }