Commit bc587acc authored by Remi  PLANEL's avatar Remi PLANEL

Rename layout phylotree to phylogram

parent 3583766c
import { hierarchy, HierarchyNode, HierarchyPointNode } from "d3-hierarchy"; import { hierarchy, HierarchyNode, HierarchyPointNode } from "d3-hierarchy";
import { RawPhyloTreeNode, PhyloTreeNode } from "../types"; import { RawPhyloTreeNode, PhyloTreeNode } from "../types";
import { scaleLinear } from "d3-scale";
import { getLeftNode, getRightNode, getDeepestNode } from "../utils/tree";
export default function () { export default function () {
let dx = 1; let dx = 1;
...@@ -12,10 +10,31 @@ export default function () { ...@@ -12,10 +10,31 @@ export default function () {
function phylotree(data: RawPhyloTreeNode) { function phylotree(data: RawPhyloTreeNode) {
// Apply the layout hierarchy. // Apply the layout hierarchy.
const root = hierarchy(data); const root = hierarchy(data);
// Compute the lengthFromRoot
root.eachBefore(computeLengthFromRoot); root.eachBefore(computeLengthFromRoot);
const { pointPhylotreeRoot, leftNode, rightNode, deepestNode } = setRelativePosition(root);
return setAbsolutePosition(pointPhylotreeRoot, leftNode, rightNode, deepestNode);
}
// Functions
function sizeNode(node: HierarchyPointNode<PhyloTreeNode>) {
node.x *= dx;
node.y = node.depth * dy;
}
function computeLengthFromRoot(node: HierarchyNode<RawPhyloTreeNode>) {
const { data: { branchLength } } = node;
node.data.branchLength = parseFloat(branchLength.toFixed(10))
node.data.lengthFromRoot = (node.parent && node.parent.data.lengthFromRoot)
? parseFloat((node.parent.data.lengthFromRoot + branchLength).toFixed(10))
: branchLength;
return node.data.lengthFromRoot;
}
function setRelativePosition() { function setRelativePosition(root: HierarchyNode<RawPhyloTreeNode>) {
const nodeWithPoint = root as HierarchyPointNode<PhyloTreeNode>; const nodeWithPoint = root as HierarchyPointNode<PhyloTreeNode>;
nodeWithPoint.x = 0; nodeWithPoint.x = 0;
nodeWithPoint.y = 0; nodeWithPoint.y = 0;
...@@ -26,7 +45,7 @@ export default function () { ...@@ -26,7 +45,7 @@ export default function () {
function computeXposition(node: HierarchyPointNode<PhyloTreeNode>) { function computeXposition(node: HierarchyPointNode<PhyloTreeNode>) {
const children = node.children; const children = node.children;
if (children) { if (children) {
node.x = (children[0].x + children[children.length - 1].x) / 2; node.x = parseFloat(((children[0].x + children[children.length - 1].x) / 2).toFixed(10));
return node.x return node.x
} }
else { else {
...@@ -35,7 +54,6 @@ export default function () { ...@@ -35,7 +54,6 @@ export default function () {
return node.x; return node.x;
} }
} }
return { return {
pointPhylotreeRoot: nodeWithPoint.eachAfter((node) => { pointPhylotreeRoot: nodeWithPoint.eachAfter((node) => {
node.y = node.data.lengthFromRoot; node.y = node.data.lengthFromRoot;
...@@ -51,14 +69,14 @@ export default function () { ...@@ -51,14 +69,14 @@ export default function () {
}; };
} }
// const maxLengthFromRoot = getMaxLenghtFromRoot();
const { pointPhylotreeRoot, leftNode, rightNode, deepestNode } = setRelativePosition();
pointPhylotreeRoot.eachBefore(n => { function setAbsolutePosition(
console.log(n.data.name, ' - [', n.x, ', ' + n.y + ']', " => ", n.data.lengthFromRoot); pointPhylotreeRoot: HierarchyPointNode<PhyloTreeNode>,
}) leftNode: HierarchyPointNode<PhyloTreeNode>,
console.log('left = ', leftNode.data.name, ' - ', leftNode.x); rightNode: HierarchyPointNode<PhyloTreeNode>,
console.log('right = ', rightNode.data.name, ' - ', rightNode.x); deepestNode: HierarchyPointNode<PhyloTreeNode>
console.log('deep = ', deepestNode.data.name, ' -', deepestNode.y); ) {
const s = leftNode === rightNode ? 1 : separation(leftNode, rightNode) / 2, const s = leftNode === rightNode ? 1 : separation(leftNode, rightNode) / 2,
tx = s - leftNode.x, tx = s - leftNode.x,
kx = dx / (rightNode.x + s + tx), kx = dx / (rightNode.x + s + tx),
...@@ -69,37 +87,17 @@ export default function () { ...@@ -69,37 +87,17 @@ export default function () {
pointPhylotreeRoot.eachBefore(sizeNode) pointPhylotreeRoot.eachBefore(sizeNode)
} else { } else {
pointPhylotreeRoot.eachBefore(function (node) { pointPhylotreeRoot.eachBefore(function (node) {
node.x = (node.x + tx) * kx; node.x = parseFloat(((node.x + tx) * kx).toFixed(1));
node.y = node.data.lengthFromRoot * ky; node.y = parseFloat((node.data.lengthFromRoot * ky).toFixed(1));
}); });
} }
pointPhylotreeRoot.eachBefore(n => {
console.log(n.data.name, ' - [', n.x, ', ' + n.y + ']');
})
return pointPhylotreeRoot; return pointPhylotreeRoot;
}
// FUnctions
function sizeNode(node: HierarchyPointNode<PhyloTreeNode>) {
node.x *= dx;
node.y = node.depth * dy;
}
function computeLengthFromRoot(node: HierarchyNode<RawPhyloTreeNode>) {
const { data: { branchLength } } = node;
node.data.branchLength = parseFloat(branchLength.toFixed(10))
node.data.lengthFromRoot = (node.parent && node.parent.data.lengthFromRoot)
? parseFloat((node.parent.data.lengthFromRoot + branchLength).toFixed(10))
: branchLength;
return node.data.lengthFromRoot;
} }
// PUBLIC
phylotree.nodeSize = function (size: [number, number]) { phylotree.nodeSize = function (size: [number, number]) {
nodeSize = true; nodeSize = true;
dx = +size[0]; dx = +size[0];
...@@ -112,6 +110,11 @@ export default function () { ...@@ -112,6 +110,11 @@ export default function () {
dy = +size[1]; dy = +size[1];
return phylotree; return phylotree;
} }
return phylotree; return phylotree;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment