Skip to content

Instantly share code, notes, and snippets.

@danielecook
Forked from mbostock/.block
Created December 14, 2017 17:45
Show Gist options
  • Save danielecook/39120306369a8bb8be8681d4e0d57526 to your computer and use it in GitHub Desktop.
Save danielecook/39120306369a8bb8be8681d4e0d57526 to your computer and use it in GitHub Desktop.
Tree of Life
license: gpl-3.0
height: 960

A re-implementation of Jason Davies’ Phylogenetic Tree of Life, with faded gray lines to connect the leaf nodes of the tree to their corresponding labels inspired by a figure from Nature.

This implementation modifies the depth of interior nodes in a cluster layout to show branch lengths. Toggle the checkbox in the top-left corner to show or hide branch lengths, and mouseover a label to highlight its path to the root.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
}
#show-length {
position: absolute;
top: 10px;
left: 10px;
}
.links {
fill: none;
stroke: #000;
}
.link-extensions {
fill: none;
stroke: #000;
stroke-opacity: .25;
}
.labels {
font: 10px sans-serif;
}
.link--active {
stroke: #000 !important;
stroke-width: 1.5px;
}
.link-extension--active {
stroke-opacity: .6;
}
.label--active {
font-weight: bold;
}
</style>
<label id="show-length">
<input type="checkbox"> Show branch length
</label>
<!-- Copyright 2011 Jason Davies https://github.com/jasondavies/newick.js -->
<script>function parseNewick(a){for(var e=[],r={},s=a.split(/\s*(;|\(|\)|,|:)\s*/),t=0;t<s.length;t++){var n=s[t];switch(n){case"(":var c={};r.branchset=[c],e.push(r),r=c;break;case",":var c={};e[e.length-1].branchset.push(c),r=c;break;case")":r=e.pop();break;case":":break;default:var h=s[t-1];")"==h||"("==h||","==h?r.name=n:":"==h&&(r.length=parseFloat(n))}}return r}</script>
<!-- Copyright 2016 Mike Bostock https://d3js.org -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var outerRadius = 960 / 2,
innerRadius = outerRadius - 170;
var color = d3.scaleOrdinal()
.domain(["Bacteria", "Eukaryota", "Archaea"])
.range(d3.schemeCategory10);
var cluster = d3.cluster()
.size([360, innerRadius])
.separation(function(a, b) { return 1; });
var svg = d3.select("body").append("svg")
.attr("width", outerRadius * 2)
.attr("height", outerRadius * 2);
var legend = svg.append("g")
.attr("class", "legend")
.selectAll("g")
.data(color.domain())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + (outerRadius * 2 - 10) + "," + (i * 20 + 10) + ")"; });
legend.append("rect")
.attr("x", -18)
.attr("width", 18)
.attr("height", 18)
.attr("fill", color);
legend.append("text")
.attr("x", -24)
.attr("y", 9)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return d; });
var chart = svg.append("g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
d3.text("life.txt", function(error, life) {
if (error) throw error;
var root = d3.hierarchy(parseNewick(life), function(d) { return d.branchset; })
.sum(function(d) { return d.branchset ? 0 : 1; })
.sort(function(a, b) { return (a.value - b.value) || d3.ascending(a.data.length, b.data.length); });
cluster(root);
var input = d3.select("#show-length input").on("change", changed),
timeout = setTimeout(function() { input.property("checked", true).each(changed); }, 2000);
setRadius(root, root.data.length = 0, innerRadius / maxLength(root));
setColor(root);
var linkExtension = chart.append("g")
.attr("class", "link-extensions")
.selectAll("path")
.data(root.links().filter(function(d) { return !d.target.children; }))
.enter().append("path")
.each(function(d) { d.target.linkExtensionNode = this; })
.attr("d", linkExtensionConstant);
var link = chart.append("g")
.attr("class", "links")
.selectAll("path")
.data(root.links())
.enter().append("path")
.each(function(d) { d.target.linkNode = this; })
.attr("d", linkConstant)
.attr("stroke", function(d) { return d.target.color; });
chart.append("g")
.attr("class", "labels")
.selectAll("text")
.data(root.leaves())
.enter().append("text")
.attr("dy", ".31em")
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (innerRadius + 4) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); })
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.text(function(d) { return d.data.name.replace(/_/g, " "); })
.on("mouseover", mouseovered(true))
.on("mouseout", mouseovered(false));
function changed() {
clearTimeout(timeout);
var t = d3.transition().duration(750);
linkExtension.transition(t).attr("d", this.checked ? linkExtensionVariable : linkExtensionConstant);
link.transition(t).attr("d", this.checked ? linkVariable : linkConstant);
}
function mouseovered(active) {
return function(d) {
d3.select(this).classed("label--active", active);
d3.select(d.linkExtensionNode).classed("link-extension--active", active).each(moveToFront);
do d3.select(d.linkNode).classed("link--active", active).each(moveToFront); while (d = d.parent);
};
}
function moveToFront() {
this.parentNode.appendChild(this);
}
});
// Compute the maximum cumulative length of any node in the tree.
function maxLength(d) {
return d.data.length + (d.children ? d3.max(d.children, maxLength) : 0);
}
// Set the radius of each node by recursively summing and scaling the distance from the root.
function setRadius(d, y0, k) {
d.radius = (y0 += d.data.length) * k;
if (d.children) d.children.forEach(function(d) { setRadius(d, y0, k); });
}
// Set the color of each node by recursively inheriting.
function setColor(d) {
var name = d.data.name;
d.color = color.domain().indexOf(name) >= 0 ? color(name) : d.parent ? d.parent.color : null;
if (d.children) d.children.forEach(setColor);
}
function linkVariable(d) {
return linkStep(d.source.x, d.source.radius, d.target.x, d.target.radius);
}
function linkConstant(d) {
return linkStep(d.source.x, d.source.y, d.target.x, d.target.y);
}
function linkExtensionVariable(d) {
return linkStep(d.target.x, d.target.radius, d.target.x, innerRadius);
}
function linkExtensionConstant(d) {
return linkStep(d.target.x, d.target.y, d.target.x, innerRadius);
}
// Like d3.svg.diagonal.radial, but with square corners.
function linkStep(startAngle, startRadius, endAngle, endRadius) {
var c0 = Math.cos(startAngle = (startAngle - 90) / 180 * Math.PI),
s0 = Math.sin(startAngle),
c1 = Math.cos(endAngle = (endAngle - 90) / 180 * Math.PI),
s1 = Math.sin(endAngle);
return "M" + startRadius * c0 + "," + startRadius * s0
+ (endAngle === startAngle ? "" : "A" + startRadius + "," + startRadius + " 0 0 " + (endAngle > startAngle ? 1 : 0) + " " + startRadius * c1 + "," + startRadius * s1)
+ "L" + endRadius * c1 + "," + endRadius * s1;
}
</script>
(
(
(
(
(
(
(
(
(
(
(
(
(
MY2147:0.025895
,
JU2906:0.0172406
):0.00287756
,
NIC511:0.0253029
):0.00162696
,
MY772:0.0318324
):0.00229935
,
JU2800:0.0421024
):0.00303837
,
(
JU1581:0.0316763
,
JU346:0.0233966
):0.00425529
):0.00211304
,
JU3128:0.0330687
):0.00100743
,
(
(
(
(
JU310:0.00729815
,
JU1530:0.0107143
):0.0125001
,
JU2534:0.0182379
):0.000787543
,
MY2535:0.0197747
):0.00159203
,
(
ED3073:0.0227043
,
NIC528:0.0452056
):0.00659833
):0.00269015
):0.00180593
,
JU2478:0.0298556
):0.000567506
,
(
(
(
(
(
(
(
(
(
(
(
MY2713:0.0113768
,
MY2693:0.00842311
):0.0141684
,
JU3135:0.02642
):0.0125592
,
GXW1:0.0294969
):0.00210052
,
(
BRC20067:0.0117554
,
JU2466:0.0111374
):0.00758348
):0.00351257
,
(
CB4852:0.00587081
,
JU1395:0.00737065
):0.0125003
):0.00221845
,
(
(
(
ED3048:0.0196129
,
NIC231:0.0171592
):0.0054857
,
CX11292:0.0178988
):0.00207746
,
CB4854:0.0418193
):0.00368666
):0.00192021
,
(
(
(
(
NIC267:0.0299075
,
NIC274:0.0399654
):0.00297467
,
MY1:0.0371503
):0.00232058
,
(
(
(
(
(
ED3052:0.0291177
,
MY679:0.0305974
):0.00197039
,
(
NIC523:0.0382537
,
JU2578:0.0241506
):0.00630189
):0.00407153
,
(
NIC272:0.0295351
,
NIC276:0.0205668
):0.0114512
):0.00167485
,
(
NIC166:0.0576477
,
JU1088:0.0410536
):0.00907399
):0.00196
,
NIC275:0.0420122
):0.00709095
):0.00175391
,
(
NIC3:0.040803
,
JU323:0.0291309
):0.00482806
):0.00394904
):0.00226686
,
(
(
(
(
(
(
(
WN2002:0.0391425
,
JU2841:0.0427043
):0.00689176
,
JU3134:0.0424809
):0.00321428
,
(
JU1896:0.0400274
,
JU1652:0.061659
):0.0081116
):0.00710848
,
JU2513:0.0369784
):0.00220836
,
MY2212:0.0407648
):0.0026198
,
(
(
JU847:0.0576687
,
ED3012:0.0277929
):0.00472357
,
JU561:0.0333439
):0.00490429
):0.00388958
,
(
(
(
ED3046:0.00859081
,
ED3049:0.0136459
):0.0370405
,
JU2464:0.041534
):0.00428759
,
(
(
(
(
(
(
(
(
(
(
(
(
MY18:0.0183579
,
MY795:0.0154257
):0.00617893
,
MY2741:0.0298112
):0.00235042
,
ED3005:0.0258383
):0.00886334
,
QX1212:0.0407796
):0.00256508
,
(
MY518:0.016992
,
ED3011:0.0288531
):0.00867148
):0.00397875
,
WN2033:0.0249507
):0.00306965
,
KR314:0.0414055
):0.0008571
,
(
DL226:0.0472775
,
JU830:0.0460443
):0.00251
):0.00313903
,
CX11285:0.0521974
):0.00219404
,
(
(
(
JU2593:0.0300154
,
JU751:0.0315336
):0.00407111
,
(
JU2829:0.0192696
,
JU2581:0.0194912
):0.0174257
):0.0135804
,
JU2587:0.0543457
):0.00465243
):0.00223116
,
CX11276:0.0597731
):0.00425246
,
(
(
(
(
(
(
(
(
QG557:0.0410055
,
JU1172:0.0263288
):0.00160034
,
(
CB4857:0.0129585
,
CB4853:0.012536
):0.00333678
):0.000718523
,
PB306:0.0440501
):0.000311363
,
(
ECA349:0.0218568
,
JU2866:0.0211484
):0.00792709
):0.00516915
,
EG4946:0.0164838
):0.00472613
,
CB4858:0.0159274
):0.00244361
,
JU2016:0.022966
):0.0025424
,
(
(
CB4855:0.0211096
,
JU2017:0.0353237
):0.00806607
,
QX1233:0.0252115
):0.00943012
):0.00486604
):0.00574961
):0.00382241
):0.00245923
):0.00104988
,
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
XZ1513:0.049999
,
ECA372:0.0489421
):0.0081253
,
XZ1515:0.0557675
):0.00740664
,
QX1794:0.060154
):0.0116092
,
QX1793:0.0663262
):0.00326831
,
QX1792:0.0589747
):0.00869026
,
(
(
ECA348:0.0325401
,
PS2025:0.0327997
):0.0102577
,
QG556:0.0435541
):0.0279359
):0.00291051
,
ECA189:0.0735288
):0.00269909
,
(
(
(
(
CX11262:0.0350972
,
CX11314:0.0201888
):0.00744222
,
CX11254:0.036038
):0.00446086
,
CX11315:0.0480912
):0.0034233
,
CX11264:0.0313695
):0.0159686
):0.00439984
,
(
(
MY16:0.0274097
,
MY23:0.0386634
):0.0226925
,
JU2879:0.0421398
):0.0270991
):0.00160706
,
(
(
DL238:0.0930101
,
CB4856:0.0851646
):0.00892293
,
(
(
(
(
(
XZ1516:0.297294
,
XZ1514:0.146901
):0.0348575
,
(
(
ECA36:0.0719335
,
QX1211:0.055353
):0.0242528
,
ECA363:0.0829033
):0.0594151
):0.0311391
,
(
ECA191:0.101805
,
ECA396:0.0650846
):0.0496377
):0.0454709
,
ECA369:0.198341
):0.0106892
,
QX1791:0.100337
):0.0095141
):0.0110797
):0.00784507
,
(
NIC268:0.0718958
,
JU2838:0.0476724
):0.00746471
):0.00182156
,
(
(
(
(
NIC252:0.0475691
,
NIC513:0.0270709
):0.00307051
,
(
(
JU2522:0.0317128
,
NIC514:0.0268695
):0.00106166
,
NIC269:0.0450277
):0.00338763
):0.0109932
,
JU2001:0.0639504
):0.00231536
,
(
(
(
(
(
EG4349:0.0456309
,
NIC266:0.0583072
):0.00452236
,
(
NIC515:0.0256774
,
JU2586:0.0294318
):0.0132393
):0.00362878
,
EG4725:0.0668093
):0.00250618
,
(
(
(
(
(
NIC251:0.0949403
,
NIC195:0.0526073
):0.0158454
,
(
(
(
(
NIC271:0.0158424
,
NIC256:0.0110079
):0.00914858
,
NIC261:0.0276369
):0.00600365
,
NIC262:0.0304997
):0.0147932
,
NIC260:0.0366409
):0.0158177
):0.0068154
,
NIC199:0.0678997
):0.00689047
,
JU258:0.0772856
):0.00479088
,
(
(
(
(
(
NIC258:0.0251175
,
JU2526:0.0427031
):0.0212377
,
JU2316:0.0337964
):0.010744
,
NIC265:0.0370738
):0.0158384
,
JU775:0.029379
):0.0123737
,
JU2519:0.0426866
):0.0170461
):0.00408793
):0.00271849
,
EG4724:0.0394669
):0.00535303
):0.00296412
):0.00187883
,
(
(
(
JU1400:0.0522712
,
MY10:0.0695899
):0.00506569
,
(
BRC20263:0.0276207
,
JU2811:0.0356448
):0.0294071
):0.00205112
,
(
QW947:0.0535821
,
JU2878:0.0437507
):0.00380646
):0.00303131
):0.00138241
,
(
(
JU3144:0.052933
,
JU2619:0.0433435
):0.00154223
,
(
QG2075:0.0474781
,
WN2001:0.0576666
):0.0103986
):0.00173566
):0.000936098
,
(
(
(
JU3125:0.0181428
,
JU3127:0.0219927
):0.0187147
,
JU774:0.0491842
):0.00305881
,
(
LKC34:0.0279431
,
ED3040:0.0295984
):0.0102042
):0.00365474
):0.0072315
):0.00118477
,
(
(
(
CX11307:0.0478684
,
QG536:0.0246276
):0.00899316
,
(
RC301:0.0116639
,
PB303:0.013335
):0.0187096
):0.00851978
,
MY2585:0.0358491
):0.0136873
):0.0017446
,
(
(
(
MY2530:0.0196796
,
MY920:0.0200714
):0.00375964
,
ED3017:0.0224744
):0.00237294
,
(
(
NIC1:0.0373184
,
ED3077:0.034777
):0.00589539
,
(
(
JU2131:0.0312973
,
JU1666:0.0239843
):0.0176537
,
DL200:0.0361125
):0.00920616
):0.00420156
):0.00459907
):0.00113905
):0.000566354
,
(
(
(
(
(
(
JU2576:0.0488602
,
NIC255:0.0258791
):0.0047367
,
NIC207:0.0302102
):0.00584073
,
CX11271:0.0296585
):0.00177221
,
(
(
(
(
NIC236:0.0416691
,
JU1491:0.0364391
):0.00678363
,
(
(
(
(
(
JU2106:0.0325181
,
WN2050:0.0223159
):0.00758153
,
JU1212:0.0521576
):0.00950948
,
JU1246:0.0363709
):0.00947862
,
JU1213:0.0391731
):0.00692417
,
(
(
(
(
JU1793:0.0394667
,
JU1580:0.0107061
):0.0131028
,
NIC501:0.0405789
):0.00565214
,
JU393:0.0312719
):0.000912275
,
(
JU2600:0.00756097
,
JU2610:0.0127018
):0.0195935
):0.00891675
):0.00928815
):0.00325681
,
(
(
(
(
(
(
(
(
JU2250:0.0117006
,
JU2570:0.0089903
):0.00200113
,
JU792:0.00900919
):0.00477995
,
JU1242:0.018991
):0.00270313
,
JU3140:0.0289206
):0.00505759
,
(
JU1934:0.0168611
,
JU2141:0.0151465
):0.00763969
):0.00690171
,
JU3132:0.0313891
):0.00222487
,
NIC527:0.0391291
):0.00173419
,
NIC242:0.0330946
):0.0035895
):0.00106145
,
(
(
JU778:0.0395944
,
NIC259:0.0298703
):0.00441728
,
JU782:0.0521116
):0.00828167
):0.0044322
):0.00190845
,
JU642:0.0271711
):0.00221126
,
(
(
EG4347:0.0238699
,
PX179:0.0106777
):0.00815541
,
JT11398:0.0278207
):0.00403527
):0.00155421
):0.0011933
,
(
(
(
(
(
JU2592:0.0335413
,
JU311:0.0219057
):0.00969927
,
MY2453:0.0300158
):0.00336478
,
(
(
JU1792:0.0167435
,
JU397:0.0254439
):0.0037674
,
CB4932:0.0140346
):0.00779267
):0.00850828
,
JU2572:0.0258005
):0.00382739
,
(
JU3137:0.0406212
,
NIC526:0.0381956
):0.00600706
):0.00193421
):0.000123262
,
(
(
(
(
JU2007:0.0299108
,
JU2862:0.0298525
):0.00150044
,
(
JU360:0.035813
,
JU1808:0.0316406
):0.00597089
):0.00180246
,
NIC529:0.0335079
):0.00110727
,
JU1409:0.0240882
):0.00328721
):0.00167972
,
(
(
(
(
NIC522:0.0231732
,
JU1440:0.014805
):0.00474566
,
AB1:0.028053
):0.00777593
,
NIC277:0.0295869
):0.00250641
,
(
(
(
(
(
(
(
(
(
(
(
JU2257:0.00900824
,
NIC1107:0.010991
):0.00428618
,
(
(
CB4851:0.00855278
,
JU394:0.0366436
):0.00645399
,
JU2825:0.0248838
):0.00436731
):0.000638686
,
JU2565:0.0117462
):0.00310793
,
JU1568:0.0153114
):0.000914391
,
JU406:0.0196526
):0.0049449
,
JU2575:0.0229256
):0.00163005
,
(
(
(
(
(
N2:0.000501987
,
LSJ1:0.000502083
):0.00505077
,
JU1200:0.00691114
):0.0025268
,
JU1543:0.0139594
):0.000694156
,
(
(
ECA252:0.00857065
,
JU2566:0.0143137
):0.00412899
,
JU1586:0.0124617
):0.003613
):0.00083708
,
NIC2:0.0118876
):0.00210988
):0.00280214
,
(
MY2573:0.00750557
,
NIC1049:0.00928277
):0.0230017
):0.00174916
,
JU2853:0.0237484
):0.00275254
,
JU2907:0.020358
):0.00217275
,
(
(
JU2234:0.0374997
,
JU440:0.0209152
):0.00374131
,
(
JU367:0.0131084
,
JU1249:0.0176577
):0.0061454
):0.00502
):0.00659292
):0.00167972
)
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment