-
Notifications
You must be signed in to change notification settings - Fork 1
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 #63 from clockor2/update-docs
docs: 📝 Update docs
- Loading branch information
Showing
26 changed files
with
349 additions
and
623 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
(((t6:0.008363424601,t1:0.008363424601):0.1843945216,t4:0.1927579462):0.9210912675,(t5:0.2590608172,(t3:0.2514467128,(t7:0.03962970241,t2:0.03962970241):0.2118170104):0.007614104384):0.8547883965); |
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,27 @@ | ||
#NEXUS | ||
[R-package APE, Thu Apr 11 13:55:53 2024] | ||
|
||
BEGIN TAXA; | ||
DIMENSIONS NTAX = 7; | ||
TAXLABELS | ||
t3 | ||
t5 | ||
t4 | ||
t7 | ||
t1 | ||
t6 | ||
t2 | ||
; | ||
END; | ||
BEGIN TREES; | ||
TRANSLATE | ||
1 t3, | ||
2 t5, | ||
3 t4, | ||
4 t7, | ||
5 t1, | ||
6 t6, | ||
7 t2 | ||
; | ||
TREE * UNTITLED = [&R] ((1:1,((((2:1,3:1):1,4:1):1,5:1):1,6:1):1):1,7:1); | ||
END; |
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 |
---|---|---|
@@ -1,27 +1,16 @@ | ||
# Handling annotations | ||
# Modifying annotations | ||
|
||
All node objects have an `annotation` field where annotations. The `annotation` fiel itself stores an object for all annotated tags. For example `Node.annotations = {Type: Blue}` for some leaf nodes in the following example. | ||
This is another example, in addition to "Annotations and Pre-Order Traversal", that shows how annotations can be modified without a Pre-Order search. | ||
|
||
Here, we show show how annotations can be extracted and modified in a loop. We swap Blue an Green type annotations to Red and Yellow on a small tree. | ||
|
||
Altered annotations are then writtedn back to newick or nexus. | ||
|
||
```typescript | ||
let newick = '((A[&Type=Blue],B[&Type=Blue]),C[&Type=Green]);' | ||
let tree = readNewick(newick) | ||
|
||
if (tree.leafList !== undefined) { // Avoids 'leafList' possibly undefined error | ||
All node objects have an `annotation` field where annotations. The `annotation` fiel itself stores an object for all annotated tags. For example `Node.annotations = {Type: Blue}` for some leaf nodes in the following example. | ||
|
||
for (let i=0; i<tree.leafList.length; i++) { | ||
if(tree.leafList[i].annotation.Type == 'Blue') { | ||
tree.leafList[i].annotation.Type = 'Red' | ||
} else { | ||
tree.leafList[i].annotation.Type = 'Yellow' | ||
} | ||
} | ||
} | ||
Altered annotations are then written back to newick. | ||
|
||
console.log(writeNewick(tree, true)) | ||
// (("A"[&"Type"="Red"]:0.0,"B"[&"Type"="Red"]:0.0):0.0,"C"[&"Type"="Yellow"]:0.0):0.0; | ||
// Note types changed ^ | ||
``` | ||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="js" data-slug-hash="vYMrRKe" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/vYMrRKe"> | ||
modify-annotations</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
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,18 @@ | ||
# Annotations and Pre-Order Traversal | ||
|
||
Here is an example that demonstrating how developers might work with node annotations and employ a pre-order traversal of a tree. We choose to demonstrate these together, since it makes sense to use them together. - If you want do do something to once node, it's likely you might want to apply it to other nodes given some logical condition. | ||
|
||
In this example, we develop a function to calculate the internal to external branch length ratio (IE ratio) of a tree - a measure of 'tippiness' with larger values corresponding to shorter external branch lengths. We then calculate the IE ratio of the subtree descending from each internal node of a starting tree, and annotate each node with this value. | ||
|
||
For those coming to PhyloJS without a computer sciance background (like the writer of this tutorial), a pre-order traversal refers to the process of applying an operation to each node in a tree starting at the root and interating through each descending node. There are many other way of trversing a tree [here](https://en.wikipedia.org/wiki/Tree_traversal). | ||
|
||
We also present this example in `TypeScript`, since it's a good example of something that might be part of a larger application where type-safety is valuable. If you want to run the example in `JavaScript`, just delete the type annotations (eg. delete `: number`, `: string`, and so on after variable declarations). You can then use the JavaScript compiler if you go to the Codepen link. | ||
|
||
One final thing to note is that the pre-order traversal in PhyloJS is a method on the `Node` class rather than the `Tree` class. Hence, when we do a pre-order traversal in the example code, we apply it as `tree.root.applyPreOrder()` to start at the root node. Why is it a method on Nodes rather than Trees? This is for flexibilty. - You might want to begin a pre-order traversal at an internal node, rather than for the tree as a whole. | ||
|
||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html" data-slug-hash="xxezGQG" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/xxezGQG"> | ||
preorder-annotations</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
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 |
---|---|---|
@@ -1,15 +1,18 @@ | ||
Here, we demonstrate how to read in a tree from a url using a `fetch()` request from the fetch API. In this case, we are reading in a list of trees used for testing. | ||
|
||
```typescript | ||
let url = 'https://raw.githubusercontent.com/clockor2/phylojs/main/test/data/egTree.nwk' | ||
let newick; | ||
|
||
fetch(url) | ||
.then(res => res.text()) | ||
.then(txt => {newick = txt}) | ||
|
||
// log first 99 characters to show newick is defined | ||
console.log(newick.slice(0,99)) | ||
// Returns: | ||
// (Jeddah-1_KF917527_camel_2013-11-08:0.0000013865,Jeddah-1_KF958702_human_2013-11-05:0.0000013652,(( | ||
``` | ||
# Reading trees from a URL | ||
|
||
Here, we demonstrate how to read in a tree from a url using a `fetch()` request from the fetch API. In this case, we read Newick trees from a URL as part of a small app that counts the number of trees in the link and plots the first one with Phylocanvas. | ||
|
||
The `fetch()` request is nested in the function `treesFromURL()`, which also handles plotting data to the screen. Key features are that the fetch request is asynchronous, so we annotate it with `await` and annotate the wrapper function with `async`. You can learn more about asynchronous function in JavaScript [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) | ||
|
||
You can copy a url linking 5 trees that we use for testing here: | ||
```text | ||
https://raw.githubusercontent.com/clockor2/phylojs/main/test/data/egTree.nwk | ||
``` | ||
|
||
|
||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html" data-slug-hash="XWQYVeV" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/XWQYVeV"> | ||
fetch-url-tree</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# Examples | ||
|
||
The following is a series of examples demonstrating how phylojs might be used in practice. | ||
The following is a series of examples demonstrating how PhyloJS might be used in practice. Interactive examples are hosted with [CodePen](https://codepen.io/collection/aMxopV). |
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,15 @@ | ||
# Ladderising Newick Trees | ||
Here is an example of an app that ladderises a user supplied Newick string. It also plots the tree with phylocanvas to show users the ladderisation. | ||
|
||
You can paste in any Newick string, or use the following for convenience: | ||
|
||
``` | ||
(t4:1,(((t2:1,t7:1):1,(t1:1,t3:1):1):1,(t6:1,t5:1):1):1); | ||
``` | ||
|
||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="ZEZovgM" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/ZEZovgM"> | ||
ladderise-app</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
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 |
---|---|---|
@@ -1,35 +1,12 @@ | ||
# Finding MRCA for a set of nodes | ||
# Extracting Clades | ||
|
||
This script demonstrates how the `getNodeByLabel`, `getMRCA`, and `getClade` methods on the `Tree` object can be wrapped in a function to find and extract subtrees given a newick string and list of desired taxa. | ||
This script demonstrates how the `getNodeByLabel`, `getMRCA`, and `getClade` methods on the `Tree` class can be wrapped in a function to find and extract clades relating a subset of tips. | ||
|
||
```typescript | ||
import { readNewick, Tree, Node } from 'phylojs'; | ||
The particular function here takes a Newick string and list of desired taxa. We use TypeScript here as this would likely be part of a larger application needing type safety. Just remove type annotations and change the compiler in codepen to run it in JavaScript. | ||
|
||
function findMRCAandExtractSubtree(newickStr: string, labels: string[]): Tree { | ||
const tree: Tree = readNewick(newickStr); | ||
const nodes: Node[] = labels.map(label => { | ||
const node = tree.getNodeByLabel(label); | ||
if (node === null) throw new Error(`No node found with label ${label}`); | ||
return node; | ||
}); | ||
|
||
const mrca = tree.getMRCA(nodes); | ||
if (mrca === null) throw new Error('MRCA is null'); | ||
|
||
const subtree: Tree = tree.getClade(mrca); | ||
|
||
return subtree; | ||
} | ||
|
||
const newickStr: string = '((A:0.1,B:0.2):0.3,(C:0.3,D:0.4):0.5,E:0.6);'; // Newick string as input | ||
const labels: string[] = ['A', 'B', 'D']; // Leaf labels to find MRCA | ||
|
||
try { | ||
const subtree: Tree = findMRCAandExtractSubtree(newickStr, labels); | ||
// Process the 'subtree' as needed | ||
// For example, you might print it to the console | ||
// console.log(subtree); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
``` | ||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="js" data-slug-hash="bGJKLjL" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/bGJKLjL"> | ||
extract-subtree</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
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 |
---|---|---|
@@ -1,49 +1,10 @@ | ||
Here we demonstrate pruning and grafting of nodes usig the `.addChild()` and `.removeChild()` methods on the `Node` class. In effect, these can be used to add or remove clades and tips. | ||
|
||
As a general node, using the `.copy()` method produces a deep copy of a node, and so is useful to avoid recursion issues with continual grafting. | ||
|
||
## Pruning | ||
```typescript | ||
let nwk = "((A,B),(C,D));" | ||
let tree = readNewick(nwk) | ||
|
||
// Get ancestor of tips A and B | ||
let node = tree.getMRCA(tree.leafList.slice(0,2)) | ||
// Prune | ||
tree | ||
.nodeList[node.parent.id] // Select node's parent by `id` | ||
.removeChild(node) // Pruning step | ||
|
||
console.log(` | ||
Original Nwk: ${nwk} | ||
Pruned Tree: ${writeNewick(tree)} | ||
`) | ||
// Returns | ||
// Original Nwk: ((A,B),(C,D)); | ||
// Pruned Tree: (("C":0.0,"D":0.0):0.0):0.0; | ||
``` | ||
|
||
## Grafting | ||
```typescript | ||
let nwk = "((A,B),(C,D));" | ||
let tree = readNewick(nwk) | ||
|
||
// Get ancestor of tips A and B. NB this is a `cherry` (A,B) | ||
let node = tree.getMRCA(tree.leafList.slice(0,2)) | ||
|
||
// Graft cherry onto tip `A` 2 times to make a ladder. | ||
for (let i=0; i<2; i++) { | ||
tree | ||
//.nodeList[node.parent.id] // Select node's parent by `id` | ||
.leafList[i] | ||
.addChild(node.copy()) // .copy() to ensure we don't bump into recursion issues | ||
} | ||
|
||
console.log(` | ||
Original Nwk: ${nwk} | ||
Pruned Tree: ${writeNewick(tree)} | ||
`) | ||
// Return | ||
// Original Nwk: ((A,B),(C,D)); | ||
// Pruned Tree: (((("A":0.0,"B":0.0):0.0)"A":0.0,(((("A":0.0,"B":0.0):0.0)"A":0.0,"B":0.0):0.0)"B":0.0):0.0,("C":0.0,"D":0.0):0.0):0.0; | ||
``` | ||
As a general note, using the `.copy()` method produces a deep copy of a node, and so is useful to avoid recursion issues, especially with iterative grafting. | ||
|
||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html" data-slug-hash="XWQYVvB" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/XWQYVvB"> | ||
prune-graft</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> |
This file was deleted.
Oops, something went wrong.
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,31 @@ | ||
# Visualisation | ||
|
||
Here is a minimal example of a small app that randomly reroots a starting tree. We parse a tree and use phylojs to reroot it randomly in a html widget. We use phylocanvas to visualise the tree. This example demonstrates rerooting, and connection with a plotting library such as phylocanvas. | ||
|
||
<p class="codepen" data-height="300" data-theme-id="dark" data-default-tab="html,result" data-slug-hash="yLrjLyL" data-editable="true" data-user="LeoFeatherstone" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> | ||
<span>See the Pen <a href="https://codepen.io/LeoFeatherstone/pen/yLrjLyL"> | ||
visualise-reroot</a> by Leo Featherstone (<a href="https://codepen.io/LeoFeatherstone">@LeoFeatherstone</a>) | ||
on <a href="https://codepen.io">CodePen</a>.</span> | ||
</p> | ||
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script> | ||
|
||
### How random rerooting works | ||
|
||
```javaScript | ||
// Randomly reroot tree on button click | ||
function onClick() { | ||
|
||
// Returns an index from 1,...,nNodes (0 is the root) | ||
let randomIndex = Math.floor(nNodes * Math.random() + 1) | ||
|
||
// Select node corresponding to index | ||
let randomNode = tree.nodeList[randomIndex] | ||
|
||
tree.reroot(randomNode) | ||
|
||
treeVis.setProps({ | ||
source: phylojs.writeNewick(tree) | ||
}) | ||
|
||
} | ||
``` |
Oops, something went wrong.