UNPKG

phylotree

Version:

A JavaScript library for developing applications and interactive visualizations involving [phylogenetic trees](https://en.wikipedia.org/wiki/Phylogenetic_tree), written as an extension of the [D3](http://d3js.org) [hierarchy layout](https://github.com/d3/

82 lines (69 loc) 2.49 kB
/** * Compute midpoint of a phylogenetic tree * * @param {Object} tree -- the phylotree.js tree object * @return {Object} the calculated midpoint to root on * { location: root_node, breakpoint: 0 } * */ export function computeMidpoint(tree) { if (!tree.hasBranchLengths()) { throw "Center of tree calculation cannot be performed on trees that do not have fully specified branch lengths"; } var bl = tree.branch_length; tree.traverse_and_compute(function(node) { if (node.parent) { var my_longest_path_length = bl(node); var my_longest_path_terminus; if (tree.isLeafNode(node)) { my_longest_path_terminus = node; node.max_path = 0; node.max_path_terminus = node; } else { my_longest_path_length += node.max_path; my_longest_path_terminus = node.max_path_terminus; } if ( !node.parent.max_path || node.parent.max_path < my_longest_path_length ) { node.parent.max_path = my_longest_path_length; node.parent.max_path_terminus = my_longest_path_terminus; } } }); var root_node = tree.getRootNode(); var longest_path_length = 0; root_node.children.forEach(function(root_child) { if (root_child.max_path_terminus !== root_node.max_path_terminus) { var pl = root_child.max_path + bl(root_child); if (pl >= longest_path_length) { longest_path_length = pl; } } }); if (root_node.max_path > longest_path_length) { // not already midpoint rooted longest_path_length = (longest_path_length + root_node.max_path) * 0.5; // start traversing up from the deepest leaf to the root, until we find the // half-way point var root_on = root_node.max_path_terminus; while (true) { var current_bl = bl(root_on); //console.log (current_bl, longest_path_length); if (current_bl <= longest_path_length) { longest_path_length -= current_bl; root_on = root_on.parent; } else { //console.log ("Rooting on ", root_on, longest_path_length[0], current_bl); return { location: root_on, breakpoint: longest_path_length / current_bl }; //console.log ("Longest " + root_path (tree.getNodeByName(root_node.max_path_terminus.name))); //console.log ("Second longest " + root_path (tree.getNodeByName(longest_path_length[1].name))); } } } return { location: root_node, breakpoint: 0 }; }