Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree render order #612

Merged
merged 6 commits into from
Aug 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ rules:
no-unneeded-ternary: ["error", { "defaultAssignment": true }]
quote-props: ["error", "as-needed"]
prefer-const: ["error", {"destructuring": "all"}]
indent: ["error", 2, {"MemberExpression": "off"}]
parserOptions:
ecmaVersion: 6
sourceType: module
Expand Down
10 changes: 2 additions & 8 deletions src/components/tree/phyloTree/change.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ const svgSetters = {
".vaccineCross": {
d: (d) => d.vaccineCross
},
".vaccineDottedLine": {
d: (d) => d.vaccineLine
},
".conf": {
d: (d) => d.confLine
}
Expand All @@ -53,9 +50,6 @@ const svgSetters = {
"stroke": (d) => d.tipStroke,
"visibility": (d) => d["visibility"]
},
".vaccineDottedLine": {
opacity: (d) => d.that.distance === "num_date" ? 1 : 0
},
".conf": {
"stroke": (d) => d.branchStroke,
"stroke-width": calcConfidenceWidth
Expand Down Expand Up @@ -159,7 +153,7 @@ export const modifySVG = function modifySVG(elemsToUpdate, svgPropsToUpdate, tra
else this.hideGrid();
}
if (elemsToUpdate.has('.regression')) {
this.svg.selectAll(".regression").remove();
this.removeRegression();
if (this.layout === "clock" && this.distance === "num_date") this.drawRegression();
}

Expand All @@ -179,7 +173,7 @@ export const modifySVG = function modifySVG(elemsToUpdate, svgPropsToUpdate, tra

/* branch labels */
if (extras.newBranchLabellingKey) {
this.svg.selectAll('.branchLabel').remove();
this.removeBranchLabels();
if (extras.newBranchLabellingKey !== "none") {
this.drawBranchLabels(extras.newBranchLabellingKey);
}
Expand Down
26 changes: 17 additions & 9 deletions src/components/tree/phyloTree/confidence.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@

export const removeConfidence = function removeConfidence(dt) {
this.confidencesInSVG = false;
if (!("confidenceIntervals" in this.groups)) return;

if (dt) {
this.svg.selectAll(".conf")
this.groups.confidenceIntervals
.selectAll("*")
.transition().duration(dt)
.style("opacity", 0)
.remove();
.style("opacity", 0)
.remove();
} else {
this.svg.selectAll(".conf").remove();
this.groups.confidenceIntervals.selectAll("*").remove();
}
};

export const drawConfidence = function drawConfidence(dt) {
this.confidencesInSVG = true;
if (!("confidenceIntervals" in this.groups)) {
this.groups.confidenceIntervals = this.svg.append("g").attr("id", "confidenceIntervals");
}
if (dt) {
this.confidence = this.svg.append("g").selectAll(".conf")
this.groups.confidenceIntervals
.selectAll(".conf")
.data(this.nodes)
.enter()
.call((sel) => this.drawSingleCI(sel, 0));
this.svg.selectAll(".conf")
this.groups.confidenceIntervals
.transition().duration(dt)
.style("opacity", 0.5);
.style("opacity", 0.5);
} else {
this.confidence = this.svg.append("g").selectAll(".conf")
this.groups.confidenceIntervals
.selectAll(".conf")
.data(this.nodes)
.enter()
.call((sel) => this.drawSingleCI(sel, 0.5));
.call((sel) => this.drawSingleCI(sel, 0.5));
}
};

Expand Down
95 changes: 59 additions & 36 deletions src/components/tree/phyloTree/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import { min, max } from "d3-array";
import { timerStart, timerEnd } from "../../../util/perf";

export const hideGrid = function hideGrid() {
this.svg.selectAll(".majorGrid").style('visibility', 'hidden');
this.svg.selectAll(".minorGrid").style('visibility', 'hidden');
this.svg.selectAll(".gridTick").style('visibility', 'hidden');
if ("majorGrid" in this.groups) {
this.groups.majorGrid.selectAll("*").style('visibility', 'hidden');
}
if ("minorGrid" in this.groups) {
this.groups.minorGrid.selectAll("*").style('visibility', 'hidden');
}
if ("gridText" in this.groups) {
this.groups.gridText.selectAll("*").style('visibility', 'hidden');
}
};

const calculateMajorGridSeperation = (range) => {
Expand Down Expand Up @@ -144,46 +150,63 @@ export const addGrid = function addGrid(layout) {
/* D3 commands to add grid + text to the DOM */

// add major grid to svg
const majorGrid = this.svg.selectAll('.majorGrid').data(majorGridPoints);
majorGrid.exit().remove(); // EXIT
majorGrid.enter().append("path") // ENTER
.merge(majorGrid) // ENTER + UPDATE
.attr("d", gridline(this.xScale, this.yScale, layout))
.attr("class", "majorGrid")
.style("fill", "none")
.style("visibility", (d) => d[1])
.style("stroke", this.params.majorGridStroke)
.style("stroke-width", this.params.majorGridWidth);
if (!("majorGrid" in this.groups)) {
this.groups.majorGrid = this.svg.append("g").attr("id", "majorGrid");
}
this.groups.majorGrid.selectAll("*").remove();
this.groups.majorGrid
.selectAll('.majorGrid')
.data(majorGridPoints)
.enter()
.append("path")
.attr("d", gridline(this.xScale, this.yScale, layout))
.attr("class", "majorGrid")
.style("fill", "none")
.style("visibility", (d) => d[1])
.style("stroke", this.params.majorGridStroke)
.style("stroke-width", this.params.majorGridWidth);

// add minor grid to SVG
const minorGrid = this.svg.selectAll('.minorGrid').data(minorGridPoints);
minorGrid.exit().remove(); // EXIT
minorGrid.enter().append("path") // ENTER
.merge(minorGrid) // ENTER + UPDATE
.attr("d", gridline(this.xScale, this.yScale, layout))
.attr("class", "minorGrid")
.style("fill", "none")
.style("visibility", (d) => d[1])
.style("stroke", this.params.minorGridStroke)
.style("stroke-width", this.params.minorGridWidth);
if (!("minorGrid" in this.groups)) {
this.groups.minorGrid = this.svg.append("g").attr("id", "minorGrid");
}
this.groups.minorGrid.selectAll("*").remove();
this.svg.selectAll(".minorGrid").remove();
this.groups.minorGrid
.selectAll('.minorGrid')
.data(minorGridPoints)
.enter()
.append("path")
.attr("d", gridline(this.xScale, this.yScale, layout))
.attr("class", "minorGrid")
.style("fill", "none")
.style("visibility", (d) => d[1])
.style("stroke", this.params.minorGridStroke)
.style("stroke-width", this.params.minorGridWidth);


/* draw the text labels for majorGridPoints */
const gridLabels = this.svg.selectAll('.gridTick').data(majorGridPoints);
const precisionX = Math.max(0, -Math.floor(Math.log10(step)));
const precisionY = Math.max(0, -Math.floor(Math.log10(yStep)));
gridLabels.exit().remove(); // EXIT
gridLabels.enter().append("text") // ENTER
.merge(gridLabels) // ENTER + UPDATE
.text((d) => d[0].toFixed(d[2]==='y' ? precisionY : precisionX))
.attr("class", "gridTick")
.style("font-size", this.params.tickLabelSize)
.style("font-family", this.params.fontFamily)
.style("fill", this.params.tickLabelFill)
.style("text-anchor", textAnchor(layout))
.style("visibility", (d) => d[1])
.attr("x", xTextPos(this.xScale, layout))
.attr("y", yTextPos(this.yScale, layout));
if (!("gridText" in this.groups)) {
this.groups.gridText = this.svg.append("g").attr("id", "gridText");
}
this.groups.gridText.selectAll("*").remove();
this.svg.selectAll(".gridText").remove();
this.groups.gridText
.selectAll('.gridText')
.data(majorGridPoints)
.enter()
.append("text")
.text((d) => d[0].toFixed(d[2]==='y' ? precisionY : precisionX))
.attr("class", "gridText")
.style("font-size", this.params.tickLabelSize)
.style("font-family", this.params.fontFamily)
.style("fill", this.params.tickLabelFill)
.style("text-anchor", textAnchor(layout))
.style("visibility", (d) => d[1])
.attr("x", xTextPos(this.xScale, layout))
.attr("y", yTextPos(this.yScale, layout));

this.grid=true;
timerEnd("addGrid");
Expand Down
28 changes: 23 additions & 5 deletions src/components/tree/phyloTree/labels.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { timerFlush } from "d3-timer";

export const updateTipLabels = function updateTipLabels(dt) {
this.svg.selectAll('.tipLabel').remove();
if ("tipLabels" in this.groups) {
this.groups.tipLabels.selectAll("*").remove();
} else {
this.groups.tipLabels = this.svg.append("g").attr("id", "tipLabels");
}

const tLFunc = this.callbacks.tipLabel;
const xPad = this.params.tipLabelPadX;
const yPad = this.params.tipLabelPadY;
Expand All @@ -20,7 +25,8 @@ export const updateTipLabels = function updateTipLabels(dt) {
}

window.setTimeout(() => {
this.tipLabels = this.svg.append("g").selectAll('.tipLabel')
this.groups.tipLabels
.selectAll('.tipLabel')
.data(inViewTerminalNodes)
.enter()
.append("text")
Expand Down Expand Up @@ -79,7 +85,8 @@ export const updateBranchLabels = function updateBranchLabels(dt) {
const visibility = createBranchLabelVisibility(this.params.branchLabelKey, this.layout, this.zoomNode.n.tipCount);
const labelSize = branchLabelSize(this.params.branchLabelKey);
const fontWeight = branchLabelFontWeight(this.params.branchLabelKey);
this.svg.selectAll('.branchLabel')
this.groups.branchLabels
.selectAll('.branchLabel')
.transition().duration(dt)
.attr("x", (d) => d.xTip - 5)
.attr("y", (d) => d.yTip - this.params.branchLabelPadY)
Expand All @@ -89,18 +96,29 @@ export const updateBranchLabels = function updateBranchLabels(dt) {
if (!dt) timerFlush();
};

export const removeBranchLabels = function removeBranchLabels() {
if ("branchLabels" in this.groups) {
this.groups.branchLabels.selectAll("*").remove();
}
};

export const drawBranchLabels = function drawBranchLabels(key) {
/* salient props: this.zoomNode.n.tipCount, this.zoomNode.n.fullTipCount */
this.params.branchLabelKey = key;
const labelSize = branchLabelSize(key);
const fontWeight = branchLabelFontWeight(key);
const visibility = createBranchLabelVisibility(key, this.layout, this.zoomNode.n.tipCount);
this.svg.append("g").selectAll('.branchLabel')

if (!("branchLabels" in this.groups)) {
this.groups.branchLabels = this.svg.append("g").attr("id", "branchLabels");
}
this.groups.branchLabels
.selectAll('.branchLabel')
.data(this.nodes.filter((d) => d.n.attr.labels && d.n.attr.labels[key]))
.enter()
.append("text")
.attr("class", "branchLabel")
.attr("x", (d) => d.xTip + ((this.params.orientation[0]>0)?-5:5) )
.attr("x", (d) => d.xTip + ((this.params.orientation[0]>0)?-5:5))
.attr("y", (d) => d.yTip - this.params.branchLabelPadY)
.style("text-anchor", (this.params.orientation[0]>0)?"end":"start")
.style("visibility", visibility)
Expand Down
1 change: 0 additions & 1 deletion src/components/tree/phyloTree/layouts.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,6 @@ export const mapToScreen = function mapToScreen() {
const xTipCross = this.xScale(d.xCross); /* x position of the center of the cross */
const yTipCross = this.yScale(d.yCross); /* x position of the center of the cross */
d.vaccineCross = ` M ${xTipCross-n},${yTipCross-n} L ${xTipCross+n},${yTipCross+n} M ${xTipCross-n},${yTipCross+n} L ${xTipCross+n},${yTipCross-n}`;
d.vaccineLine = ` M ${d.xTip},${d.yTip} L ${xTipCross},${yTipCross}`;
});
}

Expand Down
5 changes: 5 additions & 0 deletions src/components/tree/phyloTree/phyloTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const PhyloTree = function PhyloTree(reduxNodes, debugId) {
this.grid = false;
this.attributes = ['r', 'cx', 'cy', 'id', 'class', 'd'];
this.params = createDefaultParams();
this.groups = {};
/* by storing DOM <g> elements, we can quickly refer to groups here rather than scanning the DOM.
It also helps preserve the initial order of groups in the DOM as we are not creating new ones upon updates */
this.debugId = debugId; /* super useful when one is trying to debug multiple trees! */
/* create this.nodes, which is an array of nodes with properties used by phylotree for drawing.
this.nodes is the same length as reduxNodes such that this.nodes[i] is related to reduxNodes[i]
Expand Down Expand Up @@ -61,6 +64,7 @@ PhyloTree.prototype.drawTips = renderers.drawTips;
PhyloTree.prototype.drawBranches = renderers.drawBranches;
PhyloTree.prototype.drawVaccines = renderers.drawVaccines;
PhyloTree.prototype.drawRegression = renderers.drawRegression;
PhyloTree.prototype.removeRegression = renderers.removeRegression;

/* C A L C U L A T E G E O M E T R I E S E T C ( M O D I F I E S N O D E S , N O T S V G ) */
PhyloTree.prototype.setDistance = layouts.setDistance;
Expand All @@ -80,6 +84,7 @@ PhyloTree.prototype.updateConfidence = confidence.updateConfidence;

/* L A B E L S ( T I P , B R A N C H , C O N F I D E N C E ) */
PhyloTree.prototype.drawBranchLabels = labels.drawBranchLabels;
PhyloTree.prototype.removeBranchLabels = labels.removeBranchLabels;
PhyloTree.prototype.updateBranchLabels = labels.updateBranchLabels;
PhyloTree.prototype.updateTipLabels = labels.updateTipLabels;

Expand Down
Loading