Last active
May 8, 2024 17:33
-
-
Save kueda/1036776 to your computer and use it in GitHub Desktop.
Revisions
-
kueda revised this gist
Nov 27, 2013 . 3 changed files with 134 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,33 @@ Also includes a radial dendrogram visualization (branch lengths not scaled) along with some helper methods for building angled-branch trees. Copyright (c) 2013, Ken-ichi Ueda All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DOCUEMENTATION d3.phylogram.build(selector, nodes, options) Creates a phylogram. Arguments: @@ -156,7 +183,7 @@ if (!d3) { throw "d3 wasn't included!"}; } } visitPreOrder(nodes[0], function(node) { node.rootDist = (node.parent ? node.parent.rootDist : 0) + (node.length || 0) }) var rootDists = nodes.map(function(n) { return n.rootDist; }); var yscale = d3.scale.linear() @@ -255,7 +282,7 @@ if (!d3) { throw "d3 wasn't included!"}; .attr("text-anchor", 'end') .attr('font-size', '8px') .attr('fill', '#ccc') .text(function(d) { return d.length; }); vis.selectAll('g.leaf.node').append("svg:text") .attr("dx", 8) @@ -264,7 +291,7 @@ if (!d3) { throw "d3 wasn't included!"}; .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif') .attr('font-size', '10px') .attr('fill', 'black') .text(function(d) { return d.name + ' ('+d.length+')'; }); } return {tree: tree, vis: vis} This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,8 +3,8 @@ <head> <meta content='text/html;charset=UTF-8' http-equiv='content-type'> <title>Right-angle phylograms and dendrograms with d3</title> <script src="http://d3js.org/d3.v3.min.js" type="text/javascript"></script> <script src="newick.js" type="text/javascript"></script> <script src="d3.phylogram.js" type="text/javascript"></script> <script> function load() { This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,102 @@ /** * Newick format parser in JavaScript. * * Copyright (c) Jason Davies 2010. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * Example tree (from http://en.wikipedia.org/wiki/Newick_format): * * +--0.1--A * F-----0.2-----B +-------0.3----C * +------------------0.5-----E * +---------0.4------D * * Newick format: * (A:0.1,B:0.2,(C:0.3,D:0.4)E:0.5)F; * * Converted to JSON: * { * name: "F", * branchset: [ * {name: "A", length: 0.1}, * {name: "B", length: 0.2}, * { * name: "E", * length: 0.5, * branchset: [ * {name: "C", length: 0.3}, * {name: "D", length: 0.4} * ] * } * ] * } * * Converted to JSON, but with no names or lengths: * { * branchset: [ * {}, {}, { * branchset: [{}, {}] * } * ] * } */ (function(exports) { exports.parse = function(s) { var ancestors = []; var tree = {}; var tokens = s.split(/\s*(;|\(|\)|,|:)\s*/); for (var i=0; i<tokens.length; i++) { var token = tokens[i]; switch (token) { case '(': // new branchset var subtree = {}; tree.branchset = [subtree]; ancestors.push(tree); tree = subtree; break; case ',': // another branch var subtree = {}; ancestors[ancestors.length-1].branchset.push(subtree); tree = subtree; break; case ')': // optional name next tree = ancestors.pop(); break; case ':': // optional length next break; default: var x = tokens[i-1]; if (x == ')' || x == '(' || x == ',') { tree.name = token; } else if (x == ':') { tree.length = parseFloat(token); } } } return tree; }; })( // exports will be set in any commonjs platform; use it if it's available typeof exports !== "undefined" ? exports : // otherwise construct a name space. outside the anonymous function, // "this" will always be "window" in a browser, even in strict mode. this.Newick = {} ); -
kueda revised this gist
Mar 14, 2012 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,8 +3,7 @@ <head> <meta content='text/html;charset=UTF-8' http-equiv='content-type'> <title>Right-angle phylograms and dendrograms with d3</title> <script src="https://raw.github.com/mbostock/d3/master/d3.v2.js" type="text/javascript"></script> <script src="https://raw.github.com/jasondavies/newick.js/master/src/newick.js" type="text/javascript"></script> <script src="d3.phylogram.js" type="text/javascript"></script> <script> -
kueda revised this gist
Jun 21, 2011 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1 @@ Demonstration of two common tree visualizations using [d3](http://mbostock.github.com/d3) and [newick.js](https://github.com/jasondavies/newick.js). I hadn't found any examples of these kinds of right-angle trees so I figured I'd share. Input data is a Newick-formatted guide tree from a clustalw multiple sequence alignment on some cytochrome b sequences from several North American snakes. And it turns out the creator of newick.js also has an implementation of this kind of radial tree: check out [http://www.jasondavies.com/tree-of-life/](http://www.jasondavies.com/tree-of-life/) -
kueda revised this gist
Jun 21, 2011 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +1 @@ Demonstration of two common tree visualizations using [d3](http://mbostock.github.com/d3) and [newick.js](https://github.com/jasondavies/newick.js). I hadn't found any examples of these kinds of right-angle trees so I figured I'd share. Input data is a Newick-formatted guide tree from a clustalw multiple sequence alignment on some cytochrome b sequences from several North American snakes. And it turns out the creator of newick.js also has an implementation of this kind of radial tree: check out http://www.jasondavies.com/tree-of-life/ -
kueda revised this gist
Jun 20, 2011 . 2 changed files with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ Demonstration of two common tree visualizations using [d3](http://mbostock.github.com/d3) and [newick.js](https://github.com/jasondavies/newick.js). I hadn't found any examples of these kinds of right-angle trees so I figured I'd share. Input data is a Newick-formatted guide tree from a clustalw multiple sequence alignment on some cytochrome b sequences from several North American snakes. -
kueda revised this gist
Jun 20, 2011 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ Demonstration of two common tree visualizations using <a href="http://mbostock.github.com/d3/">d3</a>, <a href="https://github.com/jasondavies/newick.js">newick.js</a>. I hadn't found any examples of these kinds of right-angle trees so I figured I'd share. Input data is a Newick-formatted guide tree from a clustalw multiple sequence alignment on some cytochrome B sequences from several North American snakes. -
kueda revised this gist
Jun 20, 2011 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,7 +22,7 @@ buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: 400, skipLabels: true }) -
kueda revised this gist
Jun 20, 2011 . 2 changed files with 9 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -274,7 +274,7 @@ if (!d3) { throw "d3 wasn't included!"}; options = options || {} var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'), r = w / 2, labelWidth = options.skipLabels ? 10 : options.labelWidth || 120; var vis = d3.select(selector).append("svg:svg") .attr("width", r * 2) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,15 +22,20 @@ buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: 300, skipLabels: true }) d3.phylogram.build('#phylogram', newick, { width: 300, height: 400 }); } </script> <style type="text/css" media="screen"> body { font-family: "Helvetica Neue", Helvetica, sans-serif; } td { vertical-align: top; } </style> </head> <body onload="load()"> <table> -
kueda revised this gist
Jun 20, 2011 . 2 changed files with 18 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -273,7 +273,8 @@ if (!d3) { throw "d3 wasn't included!"}; d3.phylogram.buildRadial = function(selector, nodes, options) { options = options || {} var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'), r = w / 2, labelWidth = options.skipLabels ? 0 : options.labelWidth || 120; var vis = d3.select(selector).append("svg:svg") .attr("width", r * 2) @@ -282,7 +283,7 @@ if (!d3) { throw "d3 wasn't included!"}; .attr("transform", "translate(" + r + "," + r + ")"); var tree = d3.layout.tree() .size([360, r - labelWidth]) .sort(function(node) { return node.children ? node.children.length : -1; }) .children(options.children || function(node) { return node.branchset This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,20 +22,28 @@ buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: 250, skipLabels: true }) d3.phylogram.build('#phylogram', newick, { width: 250, height: 250 }); } </script> </head> <body onload="load()"> <table> <tr> <td> <h2>Circular Dendrogram</h2> <div id='radialtree'></div> </td> <td> <h2>Phylogram</h2> <div id='phylogram'></div> </td> </tr> </table> </body> </html> -
kueda revised this gist
Jun 20, 2011 . 2 changed files with 39 additions and 34 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -246,24 +246,26 @@ if (!d3) { throw "d3 wasn't included!"}; .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) d3.phylogram.styleTreeNodes(vis) if (!options.skipLabels) { vis.selectAll('g.inner.node') .append("svg:text") .attr("dx", -6) .attr("dy", -6) .attr("text-anchor", 'end') .attr('font-size', '8px') .attr('fill', '#ccc') .text(function(d) { return d.data.length; }); vis.selectAll('g.leaf.node').append("svg:text") .attr("dx", 8) .attr("dy", 3) .attr("text-anchor", "start") .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif') .attr('font-size', '10px') .attr('fill', 'black') .text(function(d) { return d.data.name + ' ('+d.data.length+')'; }); } return {tree: tree, vis: vis} } @@ -292,25 +294,28 @@ if (!d3) { throw "d3 wasn't included!"}; tree: tree, skipBranchLengthScaling: true, skipTicks: true, skipLabels: options.skipLabels, diagonal: d3.phylogram.radialRightAngleDiagonal() }) vis.selectAll('g.node') .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) if (!options.skipLabels) { vis.selectAll('g.leaf.node text') .attr("dx", function(d) { return d.x < 180 ? 8 : -8; }) .attr("dy", ".31em") .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif') .attr('font-size', '10px') .attr('fill', 'black') .text(function(d) { return d.data.name; }); vis.selectAll('g.inner.node text') .attr("dx", function(d) { return d.x < 180 ? -6 : 6; }) .attr("text-anchor", function(d) { return d.x < 180 ? "end" : "start"; }) .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }); } return {tree: tree, vis: vis} } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,7 +22,7 @@ buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: 250, skipLabels: true }) d3.phylogram.build('#phylogram', newick, { width: 250, -
kueda revised this gist
Jun 20, 2011 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,11 +22,11 @@ buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: 250 }) d3.phylogram.build('#phylogram', newick, { width: 250, height: 250 }); } </script> -
kueda revised this gist
Jun 20, 2011 . 1 changed file with 19 additions and 23 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,34 +8,30 @@ <script src="https://raw.github.com/jasondavies/newick.js/master/src/newick.js" type="text/javascript"></script> <script src="d3.phylogram.js" type="text/javascript"></script> <script> function load() { var newick = Newick.parse("(((Crotalus_oreganus_oreganus_cytochrome_b:0.00800,Crotalus_horridus_cytochrome_b:0.05866):0.04732,(Thamnophis_elegans_terrestris_cytochrome_b:0.00366,Thamnophis_atratus_cytochrome_b:0.00172):0.06255):0.00555,(Pituophis_catenifer_vertebralis_cytochrome_b:0.00552,Lampropeltis_getula_cytochrome_b:0.02035):0.05762,((Diadophis_punctatus_cytochrome_b:0.06486,Contia_tenuis_cytochrome_b:0.05342):0.01037,Hypsiglena_torquata_cytochrome_b:0.05346):0.00779);") var newickNodes = [] function buildNewickNodes(node, callback) { newickNodes.push(node) if (node.branchset) { for (var i=0; i < node.branchset.length; i++) { buildNewickNodes(node.branchset[i]) } } } buildNewickNodes(newick) d3.phylogram.buildRadial('#radialtree', newick, { width: parseInt(d3.select('#radialtree').style('width')) * 0.75, }) d3.phylogram.build('#phylogram', newick, { width: parseInt(d3.select('#phylogram').style('width')) * 0.75, height: newickNodes.length * 20 }); } </script> </head> <body onload="load()"> <h2>Circular Dendrogram</h2> <div id='radialtree'></div> -
kueda created this gist
Jun 20, 2011 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,317 @@ /* d3.phylogram.js Wrapper around a d3-based phylogram (tree where branch lengths are scaled) Also includes a radial dendrogram visualization (branch lengths not scaled) along with some helper methods for building angled-branch trees. d3.phylogram.build(selector, nodes, options) Creates a phylogram. Arguments: selector: selector of an element that will contain the SVG nodes: JS object of nodes Options: width Width of the vis, will attempt to set a default based on the width of the container. height Height of the vis, will attempt to set a default based on the height of the container. vis Pre-constructed d3 vis. tree Pre-constructed d3 tree layout. children Function for retrieving an array of children given a node. Default is to assume each node has an attribute called "branchset" diagonal Function that creates the d attribute for an svg:path. Defaults to a right-angle diagonal. skipTicks Skip the tick rule. skipBranchLengthScaling Make a dendrogram instead of a phylogram. d3.phylogram.buildRadial(selector, nodes, options) Creates a radial dendrogram. Options: same as build, but without diagonal, skipTicks, and skipBranchLengthScaling d3.phylogram.rightAngleDiagonal() Similar to d3.diagonal except it create an orthogonal crook instead of a smooth Bezier curve. d3.phylogram.radialRightAngleDiagonal() d3.phylogram.rightAngleDiagonal for radial layouts. */ if (!d3) { throw "d3 wasn't included!"}; (function() { d3.phylogram = {} d3.phylogram.rightAngleDiagonal = function() { var projection = function(d) { return [d.y, d.x]; } var path = function(pathData) { return "M" + pathData[0] + ' ' + pathData[1] + " " + pathData[2]; } function diagonal(diagonalPath, i) { var source = diagonalPath.source, target = diagonalPath.target, midpointX = (source.x + target.x) / 2, midpointY = (source.y + target.y) / 2, pathData = [source, {x: target.x, y: source.y}, target]; pathData = pathData.map(projection); return path(pathData) } diagonal.projection = function(x) { if (!arguments.length) return projection; projection = x; return diagonal; }; diagonal.path = function(x) { if (!arguments.length) return path; path = x; return diagonal; }; return diagonal; } d3.phylogram.radialRightAngleDiagonal = function() { return d3.phylogram.rightAngleDiagonal() .path(function(pathData) { var src = pathData[0], mid = pathData[1], dst = pathData[2], radius = Math.sqrt(src[0]*src[0] + src[1]*src[1]), srcAngle = d3.phylogram.coordinateToAngle(src, radius), midAngle = d3.phylogram.coordinateToAngle(mid, radius), clockwise = Math.abs(midAngle - srcAngle) > Math.PI ? midAngle <= srcAngle : midAngle > srcAngle, rotation = 0, largeArc = 0, sweep = clockwise ? 0 : 1; return 'M' + src + ' ' + "A" + [radius,radius] + ' ' + rotation + ' ' + largeArc+','+sweep + ' ' + mid + 'L' + dst; }) .projection(function(d) { var r = d.y, a = (d.x - 90) / 180 * Math.PI; return [r * Math.cos(a), r * Math.sin(a)]; }) } // Convert XY and radius to angle of a circle centered at 0,0 d3.phylogram.coordinateToAngle = function(coord, radius) { var wholeAngle = 2 * Math.PI, quarterAngle = wholeAngle / 4 var coordQuad = coord[0] >= 0 ? (coord[1] >= 0 ? 1 : 2) : (coord[1] >= 0 ? 4 : 3), coordBaseAngle = Math.abs(Math.asin(coord[1] / radius)) // Since this is just based on the angle of the right triangle formed // by the coordinate and the origin, each quad will have different // offsets switch (coordQuad) { case 1: coordAngle = quarterAngle - coordBaseAngle break case 2: coordAngle = quarterAngle + coordBaseAngle break case 3: coordAngle = 2*quarterAngle + quarterAngle - coordBaseAngle break case 4: coordAngle = 3*quarterAngle + coordBaseAngle } return coordAngle } d3.phylogram.styleTreeNodes = function(vis) { vis.selectAll('g.leaf.node') .append("svg:circle") .attr("r", 4.5) .attr('stroke', 'yellowGreen') .attr('fill', 'greenYellow') .attr('stroke-width', '2px'); vis.selectAll('g.root.node') .append('svg:circle') .attr("r", 4.5) .attr('fill', 'steelblue') .attr('stroke', '#369') .attr('stroke-width', '2px'); } function scaleBranchLengths(nodes, w) { // Visit all nodes and adjust y pos width distance metric var visitPreOrder = function(root, callback) { callback(root) if (root.children) { for (var i = root.children.length - 1; i >= 0; i--){ visitPreOrder(root.children[i], callback) }; } } visitPreOrder(nodes[0], function(node) { node.rootDist = (node.parent ? node.parent.rootDist : 0) + (node.data.length || 0) }) var rootDists = nodes.map(function(n) { return n.rootDist; }); var yscale = d3.scale.linear() .domain([0, d3.max(rootDists)]) .range([0, w]); visitPreOrder(nodes[0], function(node) { node.y = yscale(node.rootDist) }) return yscale } d3.phylogram.build = function(selector, nodes, options) { options = options || {} var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'), h = options.height || d3.select(selector).style('height') || d3.select(selector).attr('height'), w = parseInt(w), h = parseInt(h); var tree = options.tree || d3.layout.cluster() .size([h, w]) .sort(function(node) { return node.children ? node.children.length : -1; }) .children(options.children || function(node) { return node.branchset }); var diagonal = options.diagonal || d3.phylogram.rightAngleDiagonal(); var vis = options.vis || d3.select(selector).append("svg:svg") .attr("width", w + 300) .attr("height", h + 30) .append("svg:g") .attr("transform", "translate(20, 20)"); var nodes = tree(nodes); if (options.skipBranchLengthScaling) { var yscale = d3.scale.linear() .domain([0, w]) .range([0, w]); } else { var yscale = scaleBranchLengths(nodes, w) } if (!options.skipTicks) { vis.selectAll('line') .data(yscale.ticks(10)) .enter().append('svg:line') .attr('y1', 0) .attr('y2', h) .attr('x1', yscale) .attr('x2', yscale) .attr("stroke", "#ddd"); vis.selectAll("text.rule") .data(yscale.ticks(10)) .enter().append("svg:text") .attr("class", "rule") .attr("x", yscale) .attr("y", 0) .attr("dy", -3) .attr("text-anchor", "middle") .attr('font-size', '8px') .attr('fill', '#ccc') .text(function(d) { return Math.round(d*100) / 100; }); } var link = vis.selectAll("path.link") .data(tree.links(nodes)) .enter().append("svg:path") .attr("class", "link") .attr("d", diagonal) .attr("fill", "none") .attr("stroke", "#aaa") .attr("stroke-width", "4px"); var node = vis.selectAll("g.node") .data(nodes) .enter().append("svg:g") .attr("class", function(n) { if (n.children) { if (n.depth == 0) { return "root node" } else { return "inner node" } } else { return "leaf node" } }) .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) d3.phylogram.styleTreeNodes(vis) vis.selectAll('g.inner.node') .append("svg:text") .attr("dx", -6) .attr("dy", -6) .attr("text-anchor", 'end') .attr('font-size', '8px') .attr('fill', '#ccc') .text(function(d) { return d.data.length; }); vis.selectAll('g.leaf.node').append("svg:text") .attr("dx", 8) .attr("dy", 3) .attr("text-anchor", "start") .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif') .attr('font-size', '10px') .attr('fill', 'black') .text(function(d) { return d.data.name + ' ('+d.data.length+')'; }); return {tree: tree, vis: vis} } d3.phylogram.buildRadial = function(selector, nodes, options) { options = options || {} var w = options.width || d3.select(selector).style('width') || d3.select(selector).attr('width'), r = w / 2; var vis = d3.select(selector).append("svg:svg") .attr("width", r * 2) .attr("height", r * 2) .append("svg:g") .attr("transform", "translate(" + r + "," + r + ")"); var tree = d3.layout.tree() .size([360, r - 120]) .sort(function(node) { return node.children ? node.children.length : -1; }) .children(options.children || function(node) { return node.branchset }) .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; }); var phylogram = d3.phylogram.build(selector, nodes, { vis: vis, tree: tree, skipBranchLengthScaling: true, skipTicks: true, diagonal: d3.phylogram.radialRightAngleDiagonal() }) vis.selectAll('g.node') .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) vis.selectAll('g.leaf.node text') .attr("dx", function(d) { return d.x < 180 ? 8 : -8; }) .attr("dy", ".31em") .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) .attr('font-family', 'Helvetica Neue, Helvetica, sans-serif') .attr('font-size', '10px') .attr('fill', 'black') .text(function(d) { return d.data.name; }); vis.selectAll('g.inner.node text') .attr("dx", function(d) { return d.x < 180 ? -6 : 6; }) .attr("text-anchor", function(d) { return d.x < 180 ? "end" : "start"; }) .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }); return {tree: tree, vis: vis} } }()); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,45 @@ <!DOCTYPE html> <html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta content='text/html;charset=UTF-8' http-equiv='content-type'> <title>Right-angle phylograms and dendrograms with d3</title> <script src="https://raw.github.com/mbostock/d3/master/d3.js" type="text/javascript"></script> <script src="https://raw.github.com/mbostock/d3/master/d3.layout.js" type="text/javascript"></script> <script src="https://raw.github.com/jasondavies/newick.js/master/src/newick.js" type="text/javascript"></script> <script src="d3.phylogram.js" type="text/javascript"></script> <script> //<![CDATA[ $(document).ready(function() { var newick = Newick.parse("(((Crotalus_oreganus_oreganus_cytochrome_b:0.00800,Crotalus_horridus_cytochrome_b:0.05866):0.04732,(Thamnophis_elegans_terrestris_cytochrome_b:0.00366,Thamnophis_atratus_cytochrome_b:0.00172):0.06255):0.00555,(Pituophis_catenifer_vertebralis_cytochrome_b:0.00552,Lampropeltis_getula_cytochrome_b:0.02035):0.05762,((Diadophis_punctatus_cytochrome_b:0.06486,Contia_tenuis_cytochrome_b:0.05342):0.01037,Hypsiglena_torquata_cytochrome_b:0.05346):0.00779);") var newickNodes = [] function buildNewickNodes(node, callback) { newickNodes.push(node) if (node.branchset) { for (var i=0; i < node.branchset.length; i++) { buildNewickNodes(node.branchset[i]) } } } buildNewickNodes(newick) if ($('#radialtree').length > 0) { d3.phylogram.buildRadial('#radialtree', newick, {width: $('#radialtree').width()}) } if ($('#radialtree').length > 0) { d3.phylogram.build('#phylogram', newick, { width: $('#phylogram').width() * 0.75, height: newickNodes.length * 20 }); } }) //]]> </script> </head> <body> <h2>Circular Dendrogram</h2> <div id='radialtree'></div> <h2>Phylogram</h2> <div id='phylogram'></div> </body> </html>