/** * Create partitions from an input tree - recursive so will be called by many nodes, beginning * with root but with calculations actually beginning on leaves. * * @param partitions Partitions in the form of entries in the hash table * @param curInterestPercentage Current percentage of interest that we want splits to occur above * to view in the network later */ private ArrayList<Cluster> constructClusters( LinkedList<HashEntry> partitions, double curInterestPercentage) { ArrayList<Cluster> clusters = new ArrayList<Cluster>(); // Thresholds for the current run of the cluster builder (c.f. the threshold for the partitions // list). double curInterestThreshold = (double) (noOfTrees * (curInterestPercentage / 100.0d)); int majInterestThreshold = (int) (noOfTrees * (50.0 / 100.0d)); for (Iterator<HashEntry> it = partitions.iterator(); it.hasNext(); ) { HashEntry entry = it.next(); // Checks if this partition is still above threshold... partition. // If not: remove it - O(1). if ((double) entry.count <= curInterestThreshold) { // correct the isMajority flag to now refer to majority not if of interest or not.. if (entry.count <= majInterestThreshold) { entry.isMajority = false; } it.remove(); continue; } // Constructs clusters (list of TreeNode's for each set bit) from each partition. if ((double) entry.count > curInterestThreshold) { Cluster cluster = new Cluster(); if (entry.count > majInterestThreshold) { cluster.isMajority = true; } cluster.aboveSplit = entry.partition; cluster.noOfOccurrences = entry.count; cluster.edgeLength = entry.edgeLengthsSum / entry.count; for (int i = 0; i < entry.partition.size(); i++) { if (entry.partition.get(i)) { TreeNode node = new TreeNode(taxa.getName(i)); node.edgeLength = leafEdgeLengths[i] / noOfTrees; cluster.add(node); } } clusters.add(cluster); } } // Sort by number of taxa. // TODO: This might obviously be optimized a bit, e.g. with a PriorityQueue. - Eiriksson Collections.sort(clusters); return clusters; }
/** Constructs the majorityTree. Used to make Network so remember to call this first! */ public CTree constructMajorityTree() { int numOfNode = 0; CTree tree = new CTree(); // Creates the clusters. tree.clusters = constructClusters(partitions, resPercentage); // Begins by constructing the star tree. for (TreeNode node : tree.clusters.get(0)) { TreeNode root = tree.getRoot(); // Retrieves the root, node.parent = root; // Parent of this node -> root. root.children.add(node); // Adds this node as the children of the root. tree.nodeList.add(node); // Adds this node to the list of nodes. assert tree.nodeList.get(0).name.equals("root"); tree.parentList.put(node.name, 0); // Adds "this node -> root" parent mapping. } // Constructs internal nodes for the rest of the majority bi-partitions and rewires them. for (int z = 1; z < tree.clusters.size(); z++) { Cluster cluster = tree.clusters.get(z); // only take the majority ones....! if (cluster.isMajority == true) { // 1. Retrieves the parent of the first node in this cluster. TreeNode parent = tree.nodeList.get(tree.parentList.get(cluster.get(0).name)); // 2. Constructs a new internal node. String nodeName = "int" + Integer.toString(numOfNode); TreeNode internalNode = new TreeNode(nodeName); internalNode.addProperty("noOfOccurrences", cluster.noOfOccurrences); internalNode.edgeLength = cluster.edgeLength; internalNode.parent = parent; // 3. Insert the new node into the node list. tree.nodeList.add(internalNode); assert tree.nodeList.get(tree.nodeList.size() - 1).name.equals(internalNode.name); tree.parentList.put(nodeName, tree.nodeList.size() - 1); // update the clusters node references... // (use a method of storing edges that referenced the positions in the Tree's nodelists for // reference later.) tree.clusters.get(z).nodeRefA = tree.parentList.get(cluster.get(0).name); tree.clusters.get(z).nodeRefB = (tree.nodeList.size() - 1); for (TreeNode node : cluster) { // 4. Makes this node the child of the new internal node. node.parent = internalNode; assert node.parent.name.equals(tree.nodeList.get(tree.nodeList.size() - 1).name); tree.parentList.put(node.name, tree.nodeList.size() - 1); internalNode.children.add(node); // 5. Delete the moved node(s) from the parent's children. // TODO: optimize? probably not. for (int i = 0; i < parent.children.size(); i++) { if (parent.children.get(i).name.equals(node.name)) { parent.children.remove(i); break; } } } // Wires up the internal node. parent.children.add(internalNode); numOfNode++; } } return tree; }