Skip to content
Permalink
Browse files

Merge pull request #754 from nextstrain/unrooted-zoom

Unfurl clades during unrooted clade zoom
  • Loading branch information...
trvrb committed Jul 30, 2019
2 parents d020807 + 3a594b3 commit 841b2492182a7d3e65edbed75a55391d79e41788
@@ -250,6 +250,7 @@ export const change = function change({
/* change these things to provided value */
newDistance = undefined,
newLayout = undefined,
updateLayout = undefined,
newBranchLabellingKey = undefined,
/* arrays of data (the same length as nodes) */
branchStroke = undefined,
@@ -300,7 +301,7 @@ export const change = function change({
svgPropsToUpdate.add("stroke-width");
nodePropsToModify["stroke-width"] = branchThickness;
}
if (newDistance || newLayout || zoomIntoClade || svgHasChangedDimensions) {
if (newDistance || newLayout || updateLayout || zoomIntoClade || svgHasChangedDimensions) {
elemsToUpdate.add(".tip").add(".branch.S").add(".branch.T").add(".branch");
elemsToUpdate.add(".vaccineCross").add(".vaccineDottedLine").add(".conf");
elemsToUpdate.add('.branchLabel').add('.tipLabel');
@@ -330,12 +331,13 @@ export const change = function change({
/* distance */
if (newDistance) this.setDistance(newDistance);
/* layout (must run after distance) */
if (newDistance || newLayout) this.setLayout(newLayout || this.layout);
if (newDistance || newLayout || updateLayout) this.setLayout(newLayout || this.layout);
/* mapToScreen */
if (
svgPropsToUpdate.has(["stroke-width"]) ||
newDistance ||
newLayout ||
updateLayout ||
zoomIntoClade ||
svgHasChangedDimensions
) {
@@ -1,14 +1,18 @@
/* eslint-disable no-param-reassign */

/*
* adds the total number of descendant leaves to each node in the tree
* the functions works recursively.
* @params:
* node -- root node of the tree.
/**
* computes a measure of the total number of leaves for each node in
* the tree, weighting leaves differently if they are inView.
* Note: function is recursive
* @param {obj} node -- root node of the tree
* @returns {undefined}
* @sideEffects sets `node.leafCount` {number} for all nodes
*/
export const addLeafCount = (node) => {
if (node.terminal) {
if (node.terminal && node.inView) {
node.leafCount = 1;
} else if (node.terminal && !node.inView) {
node.leafCount = 0.15;
} else {
node.leafCount = 0;
for (let i = 0; i < node.children.length; i++) {
@@ -128,9 +128,11 @@ const unrootedPlaceSubtree = (node, nTips) => {
* @return {null}
*/
export const unrootedLayout = function unrootedLayout() {
const nTips = this.numberOfTips;

// postorder iteration to determine leaf count of every node
addLeafCount(this.nodes[0]);
const nTips = this.nodes[0].leafCount;

// calculate branch length from depth
this.nodes.forEach((d) => {d.branchLength = d.depth - d.pDepth;});
// preorder iteration to layout nodes
@@ -1,6 +1,6 @@
import { scaleLinear } from "d3-scale";
import { createDefaultParams } from "./defaultParams";
import { addLeafCount, createChildrenAndParentsReturnNumTips, setYValues } from "./helpers";
import { createChildrenAndParentsReturnNumTips, setYValues } from "./helpers";
import { change, modifySVG, modifySVGInStages } from "./change";

/* PROTOTYPES */
@@ -41,7 +41,6 @@ const PhyloTree = function PhyloTree(reduxNodes, debugId) {
this.xScale = scaleLinear();
this.yScale = scaleLinear();
this.zoomNode = this.nodes[0];
addLeafCount(this.nodes[0]);
this.strainToNode = {};
this.nodes.forEach((phylonode) => {this.strainToNode[phylonode.n.strain] = phylonode;});
/* debounced functions (AFAIK you can't define these as normal prototypes as they need "this") */
@@ -77,6 +77,9 @@ export const changePhyloTreeViaPropsComparison = (mainTree, phylotree, oldProps,
newState.selectedBranch = newTreeRedux.idxOfInViewRootNode === 0 ? null : rootNode;
newState.selectedTip = null;
newState.hovered = null;
if (newProps.layout === "unrooted") {
args.updateLayout = true;
}
}

if (oldProps.width !== newProps.width || oldProps.height !== newProps.height) {
@@ -178,6 +178,7 @@ export const months = {
export const normalNavBarHeight = 50;
export const narrativeNavBarHeight = 55;

export const NODE_NOT_VISIBLE = 0;
export const NODE_VISIBLE_TO_MAP_ONLY = 1;
export const NODE_VISIBLE = 2;
// increasing levels of "visibility"
export const NODE_NOT_VISIBLE = 0; // branch thickness 0 and excluded from map
export const NODE_VISIBLE_TO_MAP_ONLY = 1; // branch thickness 0.5 and included in map
export const NODE_VISIBLE = 2; // included on tree and map
@@ -46,9 +46,12 @@ const calcBranchThickness = (nodes, visibility, rootIdx) => {
if (!maxTipCount) {
maxTipCount = 1;
}
return nodes.map((d, idx) => (
visibility[idx] === 2 ? freqScale((d.tipCount + 5) / (maxTipCount + 5)) : 0.5
));
return nodes.map((d, idx) => {
if (visibility[idx] === NODE_VISIBLE) {
return freqScale((d.tipCount + 5) / (maxTipCount + 5));
}
return 0.5;
});
};

/* recursively mark the parents of a given node active

0 comments on commit 841b249

Please sign in to comment.
You can’t perform that action at this time.