From bc587acc934a14563e2635473d63e69ad7cb940b Mon Sep 17 00:00:00 2001 From: Remi Planel Date: Tue, 11 Jun 2019 10:57:22 +0200 Subject: [PATCH] Rename layout phylotree to phylogram --- src/scripts/layout/phylogram.ts | 126 ++++++++++++++++++++++++++++++++ src/scripts/layout/phylotree.ts | 123 ------------------------------- 2 files changed, 126 insertions(+), 123 deletions(-) create mode 100644 src/scripts/layout/phylogram.ts delete mode 100644 src/scripts/layout/phylotree.ts diff --git a/src/scripts/layout/phylogram.ts b/src/scripts/layout/phylogram.ts new file mode 100644 index 0000000..ac640a1 --- /dev/null +++ b/src/scripts/layout/phylogram.ts @@ -0,0 +1,126 @@ +import { hierarchy, HierarchyNode, HierarchyPointNode } from "d3-hierarchy"; +import { RawPhyloTreeNode, PhyloTreeNode } from "../types"; + +export default function () { + let dx = 1; + let dy = 1; + let nodeSize: boolean | null = null; + let separation = defaultSeparation; + + function phylotree(data: RawPhyloTreeNode) { + // Apply the layout hierarchy. + const root = hierarchy(data); + // Compute the lengthFromRoot + root.eachBefore(computeLengthFromRoot); + const { pointPhylotreeRoot, leftNode, rightNode, deepestNode } = setRelativePosition(root); + return setAbsolutePosition(pointPhylotreeRoot, leftNode, rightNode, deepestNode); + } + + + // Functions + function sizeNode(node: HierarchyPointNode) { + node.x *= dx; + node.y = node.depth * dy; + } + + + function computeLengthFromRoot(node: HierarchyNode) { + 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(root: HierarchyNode) { + const nodeWithPoint = root as HierarchyPointNode; + nodeWithPoint.x = 0; + nodeWithPoint.y = 0; + let previous: HierarchyPointNode | null = null; + let leftNode = nodeWithPoint; + let rightNode = nodeWithPoint; + let deepestNode = nodeWithPoint; + function computeXposition(node: HierarchyPointNode) { + const children = node.children; + if (children) { + node.x = parseFloat(((children[0].x + children[children.length - 1].x) / 2).toFixed(10)); + return node.x + } + else { + node.x = (previous) ? previous.x + separation(node, previous) : 0; + previous = node; + return node.x; + } + } + return { + pointPhylotreeRoot: nodeWithPoint.eachAfter((node) => { + node.y = node.data.lengthFromRoot; + node.x = computeXposition(node); + leftNode = (node.x <= leftNode.x) ? node : leftNode; + rightNode = (node.x >= rightNode.x) ? node : rightNode; + deepestNode = (node.y >= deepestNode.y) ? node : deepestNode; + + }), + leftNode, + rightNode, + deepestNode + }; + + } + + + function setAbsolutePosition( + pointPhylotreeRoot: HierarchyPointNode, + leftNode: HierarchyPointNode, + rightNode: HierarchyPointNode, + deepestNode: HierarchyPointNode + ) { + const s = leftNode === rightNode ? 1 : separation(leftNode, rightNode) / 2, + tx = s - leftNode.x, + kx = dx / (rightNode.x + s + tx), + ky = dy / (deepestNode.data.lengthFromRoot || 1); + + + if (nodeSize) { + pointPhylotreeRoot.eachBefore(sizeNode) + } else { + pointPhylotreeRoot.eachBefore(function (node) { + node.x = parseFloat(((node.x + tx) * kx).toFixed(1)); + node.y = parseFloat((node.data.lengthFromRoot * ky).toFixed(1)); + }); + + } + + return pointPhylotreeRoot; + } + + + // PUBLIC + phylotree.nodeSize = function (size: [number, number]) { + nodeSize = true; + dx = +size[0]; + dy = +size[1]; + return phylotree; + }; + + phylotree.size = function (size: [number, number]) { + dx = +size[0]; + dy = +size[1]; + return phylotree; + } + + + + + + return phylotree; +} + +function defaultSeparation(a: HierarchyNode | null, b: HierarchyNode | null) { + // return 1; + return (a && b && a.parent === b.parent) ? 1 : 2; +} + + diff --git a/src/scripts/layout/phylotree.ts b/src/scripts/layout/phylotree.ts deleted file mode 100644 index a431e78..0000000 --- a/src/scripts/layout/phylotree.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { hierarchy, HierarchyNode, HierarchyPointNode } from "d3-hierarchy"; -import { RawPhyloTreeNode, PhyloTreeNode } from "../types"; -import { scaleLinear } from "d3-scale"; -import { getLeftNode, getRightNode, getDeepestNode } from "../utils/tree"; - -export default function () { - let dx = 1; - let dy = 1; - let nodeSize: boolean | null = null; - let separation = defaultSeparation; - - function phylotree(data: RawPhyloTreeNode) { - // Apply the layout hierarchy. - const root = hierarchy(data); - - root.eachBefore(computeLengthFromRoot); - - function setRelativePosition() { - const nodeWithPoint = root as HierarchyPointNode; - nodeWithPoint.x = 0; - nodeWithPoint.y = 0; - let previous: HierarchyPointNode | null = null; - let leftNode = nodeWithPoint; - let rightNode = nodeWithPoint; - let deepestNode = nodeWithPoint; - function computeXposition(node: HierarchyPointNode) { - const children = node.children; - if (children) { - node.x = (children[0].x + children[children.length - 1].x) / 2; - return node.x - } - else { - node.x = (previous) ? previous.x + separation(node, previous) : 0; - previous = node; - return node.x; - } - } - - return { - pointPhylotreeRoot: nodeWithPoint.eachAfter((node) => { - node.y = node.data.lengthFromRoot; - node.x = computeXposition(node); - leftNode = (node.x <= leftNode.x) ? node : leftNode; - rightNode = (node.x >= rightNode.x) ? node : rightNode; - deepestNode = (node.y >= deepestNode.y) ? node : deepestNode; - - }), - leftNode, - rightNode, - deepestNode - }; - - } - // const maxLengthFromRoot = getMaxLenghtFromRoot(); - const { pointPhylotreeRoot, leftNode, rightNode, deepestNode } = setRelativePosition(); - pointPhylotreeRoot.eachBefore(n => { - console.log(n.data.name, ' - [', n.x, ', ' + n.y + ']', " => ", n.data.lengthFromRoot); - }) - console.log('left = ', leftNode.data.name, ' - ', leftNode.x); - console.log('right = ', rightNode.data.name, ' - ', rightNode.x); - console.log('deep = ', deepestNode.data.name, ' -', deepestNode.y); - const s = leftNode === rightNode ? 1 : separation(leftNode, rightNode) / 2, - tx = s - leftNode.x, - kx = dx / (rightNode.x + s + tx), - ky = dy / (deepestNode.data.lengthFromRoot || 1); - - - if (nodeSize) { - pointPhylotreeRoot.eachBefore(sizeNode) - } else { - pointPhylotreeRoot.eachBefore(function (node) { - node.x = (node.x + tx) * kx; - node.y = node.data.lengthFromRoot * ky; - }); - - } - - pointPhylotreeRoot.eachBefore(n => { - console.log(n.data.name, ' - [', n.x, ', ' + n.y + ']'); - }) - return pointPhylotreeRoot; - - } - - - - - // FUnctions - function sizeNode(node: HierarchyPointNode) { - node.x *= dx; - node.y = node.depth * dy; - } - function computeLengthFromRoot(node: HierarchyNode) { - 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; - } - - - phylotree.nodeSize = function (size: [number, number]) { - nodeSize = true; - dx = +size[0]; - dy = +size[1]; - return phylotree; - }; - - phylotree.size = function (size: [number, number]) { - dx = +size[0]; - dy = +size[1]; - return phylotree; - } - return phylotree; -} - -function defaultSeparation(a: HierarchyNode | null, b: HierarchyNode | null) { - // return 1; - return (a && b && a.parent === b.parent) ? 1 : 2; -} - - -- GitLab