From 07e8c42e0aa18f1742f80c8ee9a233d909b0d47c Mon Sep 17 00:00:00 2001 From: James Hadfield Date: Tue, 1 Feb 2022 16:56:44 +1300 Subject: [PATCH] [explode] add padding between subtrees The chosen value is based off testing a few datasets and we may need to tweak this in the future. --- src/components/tree/phyloTree/helpers.js | 34 +++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/components/tree/phyloTree/helpers.js b/src/components/tree/phyloTree/helpers.js index 648433512..99383b754 100644 --- a/src/components/tree/phyloTree/helpers.js +++ b/src/components/tree/phyloTree/helpers.js @@ -57,6 +57,8 @@ export const applyToChildren = (phyloNode, func) => { * Note that (sub)trees with zero tips will be have a displayOrder of undefined * @param {PhyloNode} node * @param {int} yCounter + * @sideeffect modifies node.displayOrder and node.displayOrderRange + * @returns {int} current yCounter after assignment to the tree originating from `node` */ export const setDisplayOrderRecursively = (node, yCounter) => { const children = node.n.children; // (redux) tree node @@ -75,6 +77,22 @@ export const setDisplayOrderRecursively = (node, yCounter) => { return yCounter; }; +/** + * heuristic function to return the appropriate spacing between subtrees for a given tree + * the returned value is to be interpreted as a count of the number of tips that would + * otherwise fit in the gap + */ +function _getSpaceBetweenSubtrees(numSubtrees, numTips) { + if (numSubtrees===1 || numTips<10) { + return 0; + } + if (numSubtrees*2 > numTips) { + return 0; + } + return numTips/20; /* note that it's not actually 5% of vertical space, + as the final max yCount = numTips + numSubtrees*numTips/20 */ +} + /** setDisplayOrder * given nodes, this fn sets .displayOrder for each node * Nodes are the phyloTree nodes (i.e. node.n is the redux node) @@ -83,8 +101,22 @@ export const setDisplayOrderRecursively = (node, yCounter) => { * rectangularLayout, radialLayout, createChildrenAndParents * side effects: .displayOrder (i.e. in the redux node) and .displayOrderRange * @param {Array} nodes + * @returns {undefined} */ -export const setDisplayOrder = (nodes) => setDisplayOrderRecursively(nodes[0], 0); +export const setDisplayOrder = (nodes) => { + const numSubtrees = nodes[0].n.children.filter((n) => n.fullTipCount!==0).length; + const numTips = nodes[0].n.fullTipCount; + const spaceBetweenSubtrees = _getSpaceBetweenSubtrees(numSubtrees, numTips); + let yCounter = 0; + /* iterate through each subtree, and add padding between each */ + for (const subtree of nodes[0].n.children) { + yCounter = setDisplayOrderRecursively(nodes[subtree.arrayIdx], yCounter); + yCounter+=spaceBetweenSubtrees; + } + /* note that nodes[0] is a dummy node holding each subtree */ + nodes[0].displayOrder = undefined; + nodes[0].displayOrderRange = [undefined, undefined]; +}; export const formatDivergence = (divergence) => {