Published
Edited
Mar 19, 2020
1 fork
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
simpleTree = ft.Tree.parseNewick(newickString)
Insert cell
md`Figtree js also provides a parse Nexus function that reads in a nexus sting and returns an array of trees`
Insert cell
Insert cell
html `<svg width=${width} height="400" id="simpleTree"/>`
Insert cell
margins = ({top:10,bottom:60,left:10,right:10})
Insert cell
Insert cell
simpleTreeFig=new ft.FigTree(document.getElementById("simpleTree"),margins,simpleTree)
.layout(ft.rectangularLayout)
.nodes(ft.circle())
.branches(ft.branch())

Insert cell
md`This is the output of the layout used above.`
Insert cell
ft.rectangularLayout(simpleTree)
Insert cell
md`You can explore what branch and circle are doing above with their defaults. `
Insert cell
ft.circle()
Insert cell
ft.branch()
Insert cell
md `Attributes that begin with _ are not ment to be edited directly but can be updated with getter setters, Here I'll set the circle radius to 6 and fill t0 blue.`
Insert cell
ft.circle().attr("r",6).attr("fill","blue")
Insert cell
Insert cell
html `<svg width=${width} height="400" id="simpleTreeStyles"/>`
Insert cell
{// doing this because observable tries to rerender and we don't want to overplot
d3.select(document.getElementById("simpleTreeStyles")).selectAll("g").remove();
const figtree= new ft.FigTree(document.getElementById("simpleTreeStyles"),margins,simpleTree)
.layout(ft.rectangularLayout)
.nodes(ft.circle())
.branches(ft.branch())
return figtree
}
Insert cell
html `
<style>
#simpleTreeStyles .branch .branch-path{
fill: none;
stroke: #541753;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}
#simpleTreeStyles .external-node .node-shape{
fill: #22b680;
// stroke: rgb(255, 255, 255);
// stroke-width: 1;
}

#simpleTreeStyles .internal-node .node-shape {
fill: #29c5ef;
/*stroke: rgb(255, 255, 255);*/
/*stroke-width: 1;*/
}

</style>
`
Insert cell
md`Here we'll do the same styling but using javascript. The attributes can be passed functions or primitives. Primitives will be assigned to all elements not filtered out by the filter() - default is nothing is filtered - Functions will be pasted the vertex or edge and assign the returned value. You can look at what a vertex or edge object looks like above. They have most of the same attributes as the underlying nodes in the tree, but if you need the node you can get it by using the getNode(nodeId) method on the tree and passing the vertex id. `
Insert cell
html `<svg width=${width} height="400" id="simpleTreeStylesJS1"/>`
Insert cell
{// doing this because observable tries to rerender and we don't want to overplot
d3.select(document.getElementById("simpleTreeStyles")).selectAll("g").remove();
const figtree= new ft.FigTree(document.getElementById("simpleTreeStylesJS1"),margins,simpleTree)
.layout(ft.rectangularLayout)
.nodes(ft.circle()
.attr("fill",v=>v.children?"#29c5ef":"#22b680"))
.branches(ft.branch()
.attr("stroke-width","2px")
.attr("stroke-linecap", "round")
.attr("stroke-linejoin", "round")
)
return figtree
}
Insert cell
Insert cell
html `<svg width=${width} height="400" id="simpleTreeInteractive"/>`
Insert cell
{
d3.select(document.getElementById("simpleTreeInteractive")).selectAll("g").remove();

return new ft.FigTree(document.getElementById("simpleTreeInteractive"),margins,simpleTree)
.layout(ft.rectangularLayout)
.nodes(ft.circle()
.hilightOnHover(8)
)
.branches(ft.branch()
.hilightOnHover(5)
)

}

Insert cell
html `
<style>
#simpleTreeInteractive .branch .branch-path{
fill: none;
stroke: #541753;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}

#simpleTreeInteractive .branch.hovered .branch-path{
fill: none;
stroke: #541753;
stroke-width: 4px;

}
#simpleTreeInteractive .external-node .node-shape{
fill: #22b680;
// stroke: rgb(255, 255, 255);
// stroke-width: 1;
}
#simpleTreeInteractive .external-node.hovered .node-shape{
fill: #e31e58;
// stroke: rgb(255, 255, 255);
// stroke-width: 1;
}

#simpleTreeInteractive .internal-node .node-shape {
fill: #29c5ef;
/*stroke: rgb(255, 255, 255);*/
/*stroke-width: 1;*/
}

</style>
`
Insert cell
Insert cell
ft.axis()
Insert cell
md`We'll assign it as a feature so if will update should the tree update.`
Insert cell
html `<svg width={width} height="400" id="axis-defualt"/>`
Insert cell
{
d3.select(document.getElementById("axis-defualt")).selectAll("g").remove();

return new ft.FigTree(document.getElementById("axis-defualt"),margins,simpleTree)
.layout(ft.rectangularLayout)
.nodes(ft.circle()
.hilightOnHover(8)
.rotateOnClick())
.branches(ft.branch())
.feature(ft.axis()
.location("bottom")
.y(400-margins.top-margins.bottom+5)
.x(0)
.title({text:"Divergence",
yPadding:30}))
}
Insert cell
Insert cell
Insert cell
viewof treeFile = html`<input type=file accept="text/*">`
Insert cell
localTree=Files.text(treeFile).then(t=>ft.Tree.parseNexus(t)[0])
Insert cell
treeURL = "https://raw.githubusercontent.com/evogytis/fluB/master/data/mcc%20trees/InfB_PB1t_ALLs1.mcc.tre"
Insert cell
trees = fetch(treeURL)
.then(response=>response.text()).then(string=>ft.Tree.parseNexus(string,{datePrefix:"_",dateFormat:"%Y-%m-%d"}))
Insert cell
tree = trees[0]
Insert cell
tree.orderByNodeDensity(true)
Insert cell
html`<svg width=${width} height="600" id="phylogeny"/>`
Insert cell
Insert cell
html `
<style>
#phylogeny .branch .branch-path{
fill: none;
stroke: #541753;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}

#phylogeny .branch.HA-Y .branch-path{
fill: none;
stroke: steelblue;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}

#phylogeny .branch.HA-V .branch-path{
fill: none;
stroke: #ff571a;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}
#phylogeny .branch.hovered .branch-path{
fill: none;
stroke: #541753;
stroke-width: 4px;

}
</style>
`
Insert cell
md `# libraries`
Insert cell
ft=import("https://cdn.jsdelivr.net/gh/rambaut/figtree.js@d12cb72/dist/figtree.esm.js")
Insert cell
d3=require("d3")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more