void StitchTreeFunction::recursivelyCleanPatchClade(TopologyNode* node, TopologyNode*& newRoot, std::set<Taxon>& remainingTaxa, size_t& index, size_t patchIndex) { // remove self if found in remainingTaxa if (node->isTip()) { std::set<Taxon>::iterator it = remainingTaxa.find( node->getTaxon() ); if (it != remainingTaxa.end()) { remainingTaxa.erase( node->getTaxon() ); TopologyNode* parent = &node->getParent(); std::vector<TopologyNode*> children = parent->getChildren(); for (size_t i = 0; i < children.size(); i++) { children[i]->setParent(NULL); parent->removeChild(children[i]); if (children[i] != node) newRoot = children[i]; else delete children[i]; } // free old root node delete parent; } return; } // recurse towards tips std::vector<TopologyNode*> children = node->getChildren(); for (size_t i = 0; i < children.size(); i++) { recursivelyCleanPatchClade(children[i], newRoot, remainingTaxa, index, patchIndex); } return; }
int PruneTreeFunction::recursivelyRetainTaxa(RevBayesCore::TopologyNode *node) { // tip node if (node->isTip()) { const std::vector<Taxon>& taxa = tau->getValue().getTaxa(); const Taxon& tipTaxon = taxa[node->getIndex()]; std::set<Taxon>::iterator it = retainedTaxa.find( tipTaxon ); // found it if (it != retainedTaxa.end()) { // std::cout << "retain\t" << node->getIndex() << "\t" << node << "\t" << tipTaxon.getName() << "\n"; return 1; } else { // std::cout << "prune\t" << node->getIndex() << "\t" << node << "\t" << tipTaxon.getName() << "\n"; return 0; } } int total_count = 0; int number_children_retained = 0; // determine if subclade has any retained taxa std::vector<TopologyNode*> children = node->getChildren(); std::vector<int> count( children.size(), 0 ); for (size_t i = 0; i < children.size(); i++) { // std::cout << "recurse\t" << node->getIndex() << "\t" << node << "\tfor child\t" << children[i]->getIndex() << "\t" << children[i] << "\n"; // count[i] = recursivelyRetainTaxa(children[i]); pruneCount[ children[i] ] = recursivelyRetainTaxa(children[i]); total_count += pruneCount[ children[i] ]; if (pruneCount[ children[i] ] > 0) number_children_retained++; } if (node->isRoot()) { TopologyNode* root = node; if (number_children_retained == 0) { } // if one daughter, patch over node else if (number_children_retained == 1) { std::vector<TopologyNode*> fresh_children = node->getChildren(); for (size_t i = 0; i < fresh_children.size(); i++) { // remove all of the node's children // NB: node->removeAllChildren() also calls delete node->removeChild(fresh_children[i]); // std::cout << "del-child\t" << fresh_children[i]->getIndex() << "\t" << fresh_children[i] << "\t" << fresh_children[i]->getTaxon().getName() << "\n"; } for (size_t i = 0; i < fresh_children.size(); i++) { if (pruneCount[ fresh_children[i] ] == 0) continue; root = fresh_children[i]; fresh_children[i]->setParent(NULL); // std::cout << "add-child\t" << fresh_children[i]->getIndex() << "\t" << fresh_children[i] << "\t" << fresh_children[i]->getTaxon().getName() << "\n"; } node->setParent(NULL); // free memory // delete node; // setRoot will free this memory } // check ntaxa > 2 bool good = true; if (!good) { throw RbException(""); } value->setRoot( root, true ); std::vector<TopologyNode*> nodes = value->getNodes(); // update tip nodes with stored taxon-index for (size_t i = 0; i < value->getNumberOfTips(); i++) { nodes[i]->setIndex( retainedIndices[ nodes[i]->getTaxon() ] ); } // value->setRoot( root, false ); value->setRoot(root, true); } else if (node->isInternal()) { // std::cout << "patch\t" << node->getIndex() << "\t" << node << "\n"; // if zero daughters, drop all daughters if (number_children_retained == 0) { node->removeAllChildren(); } // if one daughter, patch over node else if (number_children_retained == 1) { std::vector<TopologyNode*> fresh_children = node->getChildren(); TopologyNode* parent = &node->getParent(); // want to retain order of fresh_children for parent... std::vector<TopologyNode*> fresh_parent_children = parent->getChildren(); for (size_t i = 0; i < fresh_children.size(); i++) { // remove all of the node's children // NB: node->removeAllChildren() also calls delete node->removeChild(fresh_children[i]); // std::cout << "del-child\t" << pruneCount[ fresh_children[i] ] << "\t" << fresh_children[i]->getIndex() << "\t" << fresh_children[i] << "\t" << fresh_children[i]->getTaxon().getName() << "\n"; } for (size_t i = 0; i < fresh_children.size(); i++) { if ( pruneCount[ fresh_children[i] ] == 0) continue; fresh_children[i]->setParent(parent); parent->addChild(fresh_children[i]); // std::cout << "add-child\t" << pruneCount[ fresh_children[i] ] << "\t" << fresh_children[i]->getIndex() << "\t" << fresh_children[i] << "\t" << fresh_children[i]->getTaxon().getName() << "\n"; } node->setParent(NULL); parent->removeChild(node); // free memory delete node; } // if two or more daughters, do not prune // ... return total_count; } else { throw RbException("fnPruneTree encountered unexpected type of node!"); } return true; }