-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from stephenshank/docs
Examples and unit tests
- Loading branch information
Showing
24 changed files
with
1,630 additions
and
7 deletions.
There are no files selected for viewing
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,352 @@ | ||
<!DOCTYPE html> | ||
<html lang='en'> | ||
|
||
<head> | ||
<meta charset="utf-8"> | ||
|
||
<link href="//veg.github.io/phylotree.js/phylotree.css" rel="stylesheet"> | ||
|
||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> | ||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"> | ||
|
||
<script src="//code.jquery.com/jquery.js"></script> | ||
<script src="//netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> | ||
<script src="//d3js.org/d3.v3.min.js"></script> | ||
<script src="../../phylotree.js"></script> | ||
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | ||
|
||
<style> | ||
.date-text { | ||
padding: 0.25em; | ||
text-align: center; | ||
} | ||
|
||
.size-bubble, | ||
.size-bubble * { | ||
fill: #CCC; | ||
shape-rendering: crispEdges; | ||
stroke: black; | ||
stroke-width: 2px; | ||
} | ||
|
||
.size-label { | ||
display: block; | ||
text-align: center; | ||
font-family: sans-serif; | ||
font-size: 12pt; | ||
} | ||
|
||
|
||
@media print { | ||
.no-print, | ||
.no-print * { | ||
display: none !important; | ||
} | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div class="container"> | ||
<div class="row no-print"> | ||
<div class="col-md-4"> | ||
|
||
<div> | ||
<form> | ||
<label>Radial layout </label> | ||
<input type="checkbox" id="layout" / checked> | ||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#newick_modal">Input Newick</button | ||
</form> | ||
</div> | ||
|
||
</div> | ||
</div> | ||
|
||
<div class = "row"> | ||
<div class = "col-md-12"> | ||
<svg id="tree_display"></svg> | ||
</div> | ||
</div> | ||
|
||
<div class = "row"> | ||
<div class = "col-md-2" id = "compartment-legend"> | ||
</div> | ||
<div class = "col-md-2" id="size-legend"> | ||
</div> | ||
<div class = "col-md-2" id="date-legend"> | ||
</div> | ||
</div> | ||
|
||
<div class="modal" id = 'newick_modal'> | ||
<div class="modal-dialog"> | ||
<div class="modal-content"> | ||
<div class="modal-header"> | ||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> | ||
<h4 class="modal-title">Newick string to render</h4> | ||
</div> | ||
<div class="modal-body" id='newick_body'> | ||
<textarea id='nwk_spec' autofocus=t rue placeholder="" style='width: 100%; height: 100%' rows=2 0 selectionStart=1 selectionEnd=1 000>(a : 0.1, (b : 0.11, (c : 0.12, d : 0.13) : 0.14) : 0.15)</textarea> | ||
</div> | ||
<div class="modal-footer"> | ||
<button type="button" class="btn btn-primary" id='validate_newick'>Display this tree</button> | ||
</div> | ||
</div> | ||
<!-- /.modal-content --> | ||
</div> | ||
<!-- /.modal-dialog --> | ||
</div> | ||
<!-- /.modal --> | ||
|
||
<script> | ||
// use these formats for parsing and displaying sampling dates | ||
var date_in = d3.time.format("%Y%m%d"), | ||
date_out = d3.time.format("%B %d, %Y"); | ||
|
||
// default scheme to color by date | ||
var coloring_scheme = d3.scale.category10(); | ||
|
||
// different shapes for labeling compartments | ||
var compartment_labels = d3.scale.ordinal().range(["circle", "square", "diamond", "triangle-down", "triangle-up"]); | ||
|
||
// global tree object | ||
var tree; | ||
|
||
|
||
// bubble size scale | ||
var size_scale = d3.scale.pow().exponent(0.4).range([1, 10]).clamp(false).domain([0, 1]); | ||
|
||
// determines the size of a node "bubble" | ||
|
||
function bubbleSize(node) { | ||
if (node && node.copy_number) { | ||
return size_scale(node.copy_number); | ||
} | ||
return 1; | ||
} | ||
|
||
function nodeStyler(container, node) { | ||
if (d3.layout.phylotree.is_leafnode(node)) { | ||
|
||
var existing_circle = container.selectAll("circle"); | ||
|
||
if (existing_circle.size() == 1) { | ||
existing_circle.remove(); | ||
} | ||
|
||
if (node.copy_number) { | ||
existing_circle = container.selectAll("path.node_shape").data([node.compartment]); | ||
existing_circle.enter().append("path").classed("node_shape", true); | ||
|
||
var bubble_size = tree.node_bubble_size(node); | ||
|
||
var label = existing_circle.attr("d", function(d) { | ||
return d3.svg.symbol().type(compartment_labels(d)).size(bubble_size * bubble_size)(); | ||
}).selectAll("title").data([node.copy_number]); | ||
label.enter().append("title"); | ||
label.text("" + node.copy_number + " copies"); | ||
|
||
|
||
existing_circle.style("stroke-width", "1px").style("stroke", "black"); | ||
if (node.text_angle) { | ||
existing_circle.attr("transform", function(d) { | ||
return "rotate(" + node.text_angle + ") translate(" + (node.text_align == "end" ? -1 : 1) * bubble_size / 2 + ",0)"; | ||
}); | ||
} else { | ||
existing_circle.attr("transform", function(d) { | ||
return "translate(" + bubble_size / 2 + ",0)"; | ||
}); | ||
} | ||
} | ||
|
||
} | ||
|
||
if (node.date) { | ||
var node_color = coloring_scheme(node.date); | ||
container.selectAll("circle").style("fill", node_color); | ||
container.selectAll("path").style("fill", node_color); | ||
container.style("fill", node_color); | ||
} | ||
|
||
} | ||
|
||
function drawATree(newick) { | ||
|
||
tree = d3.layout.phylotree() | ||
.svg(d3.select("#tree_display")) | ||
.options({ | ||
'selectable': false, | ||
// make nodes and branches not selectable | ||
'collapsible': false, | ||
// turn off the menu on internal nodes | ||
'transitions': false, | ||
// turn off d3 animations. | ||
'draw-size-bubbles': true, | ||
// draw node size bubbles | ||
'annular-limit': 0.9 | ||
// controls how much of the overall diameter can be taken by | ||
// empty "annular" space | ||
}) | ||
.node_span(bubbleSize) | ||
.style_nodes(nodeStyler) | ||
.node_circle_size(0) // do not draw clickable circles for internal nodes | ||
.branch_name(function() { | ||
return "" | ||
}) // no leaf names | ||
; | ||
|
||
|
||
/* the next call creates the tree object, and tree nodes */ | ||
tree(d3.layout.newick_parser(newick)); | ||
|
||
/* parse tip names which are assumed to be like this: | ||
T0104_20140512_env_CSF_319_130 | ||
splitting on '_' yields | ||
-- Patient ID (T0104); ignored | ||
-- YYYYMMDD sample date; parsed and used to assign *colors* to edges/nodes | ||
-- gene; ignored | ||
-- compartment; parsed and used to assign *shapes* to nodes | ||
-- clone ID; ignored [any other numeric fields with indices 4 through length-2 will be ignored] | ||
-- copy number; parsed and used to scale "bubbles" on leaves | ||
tips which do not conform to this naming convention are labeled as "reference", | ||
and annotated using a special character. | ||
*/ | ||
|
||
var unique_compartments = {}, | ||
unique_dates = {}; | ||
|
||
var copy_number_range = [1e100, 0], | ||
attributed_node = null; | ||
|
||
_.each(tree.get_nodes(), function(value, key) { | ||
var attributes = value.name.split('_'); | ||
if (attributes.length >= 5) { | ||
attributed_node = value; | ||
|
||
value.compartment = attributes[3]; | ||
value.copy_number = Math.max(1, parseFloat(attributes[attributes.length - 1])); | ||
|
||
|
||
copy_number_range[0] = Math.min(copy_number_range[0], value.copy_number); | ||
copy_number_range[1] = Math.max(copy_number_range[1], value.copy_number); | ||
|
||
value.date = date_out(date_in.parse(attributes[1])); | ||
unique_compartments[value.compartment] = 1; | ||
unique_dates[attributes[1]] = 1; | ||
} else { | ||
value.is_reference = true; | ||
} | ||
|
||
}); | ||
|
||
|
||
|
||
size_scale.domain(copy_number_range); | ||
coloring_scheme.domain(_.keys(unique_dates).sort().map(function(d) { | ||
return date_out(date_in.parse(d)) | ||
})); | ||
compartment_labels.domain(_.keys(unique_compartments).sort()); | ||
|
||
|
||
if ($("#layout").prop("checked")) { | ||
tree.radial(true); | ||
} | ||
tree.placenodes().layout(); | ||
|
||
var rescale = tree.node_bubble_size(attributed_node) / size_scale(attributed_node.copy_number) * 0.5, | ||
rescaled_size = _.compose(function(d) { | ||
return d * rescale | ||
}, size_scale); | ||
|
||
// create a legend for sizes | ||
// power of 10 ticks | ||
|
||
var size_bubbles = _.map(d3.range(Math.floor(Math.log(copy_number_range[0]) / Math.log(10)), 1 + Math.ceil(Math.log(copy_number_range[1]) / Math.log(10))), | ||
function(v) { | ||
return Math.pow(10, v); | ||
}); | ||
|
||
d3.select("#size-legend").selectAll(".row").remove(); | ||
var reference_sizes = d3.select("#size-legend").selectAll(".row").data(_.map(size_bubbles, function(d) { | ||
return [d]; | ||
})); | ||
reference_sizes.enter().append("div").classed("row", true).selectAll(".col-md-2").data(function(d) { | ||
return [d]; | ||
}).enter().append("div").classed("col-md-2", true); | ||
|
||
var max_size = rescaled_size(size_bubbles[size_bubbles.length - 1]); | ||
|
||
reference_sizes.selectAll(".col-md-2").each(function(d) { | ||
var circle_size = rescaled_size(d); | ||
d3.select(this).append("svg").attr("width", 2 * max_size + 4).attr("height", 2 * circle_size + 4).append("circle").classed("size-bubble", true).attr("r", circle_size).attr("cx", max_size + 2).attr("cy", circle_size + 2); | ||
d3.select(this).append("span").classed("size-label", true).style("width", "" + (2 * max_size + 4) + "px").text(d); | ||
}); | ||
|
||
|
||
// create a legend for compartments | ||
|
||
d3.select("#compartment-legend").selectAll(".row").remove(); | ||
var compartment_depictions = d3.select("#compartment-legend").selectAll(".row").data(compartment_labels.domain()); | ||
compartment_depictions.enter().append("div").classed("row", true).selectAll(".col-md-2").data(function(d) { | ||
return [d]; | ||
}).enter().append("div").classed("col-md-2", true); | ||
compartment_depictions.exit().remove(); | ||
|
||
compartment_depictions.selectAll(".col-md-2").each(function(d) { | ||
d3.select(this).append("svg").attr("width", 2 * max_size + 4).attr("height", 2 * max_size + 4).append("path").classed("size-bubble", true).attr("d", function(d) { | ||
return d3.svg.symbol().type(compartment_labels(d)).size(max_size * max_size)(); | ||
}).attr("transform", "translate( " + max_size + "," + max_size + ")"); | ||
|
||
d3.select(this).append("span").classed("size-label", true).style("width", "" + (2 * max_size + 4) + "px").text(d); | ||
}); | ||
|
||
// create a legend for dates | ||
d3.select("#date-legend").selectAll(".row").remove(); | ||
var date_colors = d3.select("#date-legend").selectAll(".row").data(coloring_scheme.domain()); | ||
date_colors.enter().append("div").classed("row", true); | ||
date_colors.exit().remove(); | ||
|
||
date_colors.each(function(d) { | ||
d3.select(this).style("background-color", coloring_scheme(d)).classed("date-text", true).text(d).style("color", d3.rgb(coloring_scheme(d)).hsl().l < 0.5 ? "white" : "black"); | ||
}); | ||
|
||
|
||
// UI handlers | ||
$("#layout").on("click", function(e) { | ||
tree.radial($(this).prop("checked")).placenodes().update(); | ||
}); | ||
|
||
|
||
} | ||
|
||
function loadTreeFromURL(url) { | ||
d3.text(url, function(error, newick) { | ||
|
||
drawATree(newick); | ||
}); | ||
} | ||
|
||
$("#validate_newick").on("click", function(e) { | ||
var res = d3_phylotree_newick_parser($('textarea[id$="nwk_spec"]').val(), true); | ||
if (res["error"] || !res["json"]) { | ||
var warning_div = d3.select("#newick_body").selectAll("div .alert-danger").data([res["error"]]) | ||
warning_div.enter().append("div"); | ||
warning_div.html(function(d) { | ||
return d; | ||
}).attr("class", "alert-danger"); | ||
|
||
} else { | ||
drawATree($('textarea[id$="nwk_spec"]').val()); | ||
$('#newick_modal').modal('hide'); | ||
} | ||
}); | ||
|
||
loadTreeFromURL("tree.nwk"); | ||
</script> | ||
|
||
</body> | ||
|
||
</html> |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
(((T0104_20140512_env_PBMC_11_676:5.3E-4,(T0104_20140512_env_PBMC_7_34:5.3E-4,(T0104_20140512_env_CSF_41_67:5.5E-4,(((T0104_20140512_env_CSF_38_125:5.5E-4,T0104_20140512_env_CSF_21_66:5.5E-4):5.5E-4,(T0104_20140512_env_CSF_24_62:5.5E-4,(T0104_20140512_env_CSF_35_153:5.5E-4,T0104_20140512_env_PBMC_6_48:5.5E-4):0.00297):0.00294):0.00168,T0104_20140512_env_CSF_18_125:0.00593):8.7E-4):0.00431):0.00432):0.00579,(((((T0104_20140512_env_PBMC_12_129:5.4E-4,(T0104_20140512_env_PBMC_63_31:0.00766,(T0104_20140512_env_PBMC_17_49:0.00309,T0104_20140512_env_PBMC_35_31:5.4E-4):0.00297):0.00392):0.00326,(T0104_20140512_env_PBMC_46_118:0.00631,((T0104_20140512_env_PBMC_2_734:5.4E-4,((T0104_20140512_env_PBMC_28_73:0.00306,T0104_20140512_env_PBMC_43_166:0.00591):0.0057,T0104_20140512_env_PBMC_56_156:0.00604):5.4E-4):0.00583,(T0104_20140512_env_PBMC_65_71:5.4E-4,T0104_20140512_env_PBMC_71_109:0.0031):0.00604):5.4E-4):0.00307):0.00239,T0104_20140512_env_PBMC_20_156:0.00896):5.5E-4,T0104_20140512_env_CSF_75_117:5.5E-4):0.00288,(T0104_20140512_env_PBMC_4_406:0.00302,(((T0104_20140512_env_CSF_57_56:0.01035,T0104_20140512_env_PBMC_38_31:0.00342):0.02318,((T0104_20140512_env_PBMC_26_43:5.5E-4,(T0104_20140512_env_PBMC_82_59:5.5E-4,T0104_20140512_env_PBMC_260_36:0.00935):0.01074):0.00356,T0104_20140512_env_PBMC_21_108:5.4E-4):5.4E-4):0.01498,(((T0104_20140512_env_CSF_423_43:5.5E-4,(T0104_20140512_env_CSF_390_53:0.00891,T0104_20140512_env_CSF_104_154:0.00601):5.2E-4):0.00247,(T0104_20140512_env_CSF_4_72:0.00303,(T0104_20140512_env_CSF_85_41:5.5E-4,(T0104_20140512_env_CSF_3_2552:8.2E-4,T0104_20140512_env_CSF_49_59:5.5E-4):6.0E-4):5.2E-4):0.00101):0.00295,((T0104_20140512_env_PBMC_62_42:0.00603,(T0104_20140512_env_PBMC_0_3329:5.5E-4,((T0104_20140512_env_CSF_26_85:5.5E-4,(T0104_20140512_env_CSF_1_9127:5.5E-4,(T0104_20140512_env_CSF_293_139:0.00379,T0104_20140512_env_PBMC_99_49:0.0031):0.00476):5.5E-4):6.9E-4,T0104_20140512_env_CSF_27_107:0.0030):0.00126):5.7E-4):0.0050,(T0104_20140512_env_CSF_319_130:5.5E-4,(T0104_20140512_env_CSF_80_58:0.00299,(T0104_20140512_env_CSF_2_69:0.00309,((T0104_20140512_env_CSF_122_65:5.5E-4,(T0104_20140512_env_CSF_23_120:5.5E-4,(T0104_20140512_env_CSF_52_52:0.0030,T0104_20140512_env_PBMC_193_47:5.5E-4):5.4E-4):0.00297):0.00297,((T0104_20140512_env_CSF_20_73:5.5E-4,T0104_20140512_env_PBMC_49_35:5.5E-4):0.00434,(T0104_20140512_env_CSF_22_57:0.00302,((((T0104_20140512_env_CSF_13_90:0.00455,T0104_20140512_env_PBMC_78_155:0.00302):0.00452,(T0104_20140512_env_CSF_44_140:5.3E-4,T0104_20140512_env_CSF_187_155:5.3E-4):5.3E-4):5.6E-4,(T0104_20140512_env_CSF_8_181:5.5E-4,T0104_20140512_env_PBMC_164_54:5.5E-4):0.00302):5.3E-4,T0104_20140512_env_CSF_7_73:0.00297):0.00179):7.7E-4):5.5E-4):5.5E-4):5.4E-4):5.3E-4):8.2E-4):5.4E-4):5.4E-4):6.7E-4):0.00439):5.5E-4):0.001955,((T0104_20140512_env_PBMC_73_89:0.00557,T0104_20140512_env_PBMC_115_53:0.00601):5.0E-4,(((T0104_20140512_env_PBMC_110_48:0.00294,(T0104_20140512_env_PBMC_127_31:0.0031,(T0104_20140512_env_PBMC_16_369:5.2E-4,T0104_20140512_env_PBMC_3_139:0.00933):5.5E-4):0.0114):0.02769,((T0104_20140512_env_PBMC_8_112:0.00299,(T0104_20140512_env_PBMC_14_225:0.00623,(T0104_20140512_env_PBMC_72_138:5.4E-4,T0104_20140512_env_PBMC_96_75:0.00301):0.00425):5.3E-4):0.00429,T0104_20140512_env_PBMC_52_46:0.0059):5.3E-4):0.00566,(T0104_20140512_env_PBMC_117_57:5.5E-4,((T0104_20140512_env_PBMC_30_427:5.4E-4,T0104_20140512_env_PBMC_175_50:0.00916):0.00573,T0104_20140512_env_PBMC_154_54:0.00304):5.4E-4):0.0059):5.5E-4):8.95E-4); |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
PSTVd,TASVd,TCDVd,CSVd,CLVd,CCCVd,ASSVd,PBCVd,CVd-OS,CbVd-1,CbVd-2,CbVd-3,CCHMVd,ELVd,ASBVd,HSVd,CVdIV,CVDIII,CBLVd,CEVd,PLMVd | ||
1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,2 |
Oops, something went wrong.