Skip to content

Commit

Permalink
🚧 rename: make Base explicit, Layout implicit
Browse files Browse the repository at this point in the history
  • Loading branch information
victorlin committed Nov 5, 2024
1 parent 3d305fb commit 12aff24
Show file tree
Hide file tree
Showing 17 changed files with 194 additions and 194 deletions.
18 changes: 9 additions & 9 deletions src/actions/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { createVisibleLegendValues, getLegendOrder } from "../util/colorScale";
import { getTraitFromNode } from "../util/treeMiscHelpers";
import { warningNotification } from "./notifications";
import { calcFullTipCounts, calcTipCounts } from "../util/treeCountingHelpers";
import { PhyloNode } from "../components/tree/phyloTree/types";
import { PhyloNodeBase } from "../components/tree/phyloTree/types";
import { Metadata } from "../metadata";
import { AppDispatch, RootState } from "../store";
import { ReduxNode, TreeState } from "../reducers/tree";
import { ReduxNodeBase, TreeState } from "../reducers/tree";

/** [root idx tree1, root idx tree2] */
export type Root = [number | undefined, number | undefined]
Expand All @@ -39,20 +39,20 @@ export const applyInViewNodesToTree = (
d.shell.update = true;
});
if (tree.nodes[validIdxRoot].hasChildren) {
applyToChildren(tree.nodes[validIdxRoot].shell, (d: PhyloNode) => {d.inView = true;});
applyToChildren(tree.nodes[validIdxRoot].shell, (d: PhyloNodeBase) => {d.inView = true;});
} else if (tree.nodes[validIdxRoot].parent.arrayIdx===0) {
// subtree with n=1 tips => don't make the parent in-view as this will cover the entire tree!
tree.nodes[validIdxRoot].shell.inView = true;
} else {
applyToChildren(tree.nodes[validIdxRoot].parent.shell, (d: PhyloNode) => {d.inView = true;});
applyToChildren(tree.nodes[validIdxRoot].parent.shell, (d: PhyloNodeBase) => {d.inView = true;});
}
} else {
/* FYI applyInViewNodesToTree is now setting inView on the redux nodes */
tree.nodes.forEach((d) => {
d.inView = false;
});
/* note that we cannot use `applyToChildren` as that operates on PhyloNodes */
const _markChildrenInView = (node: ReduxNode) => {
const _markChildrenInView = (node: ReduxNodeBase) => {
node.inView = true;
if (node.children) {
for (const child of node.children) _markChildrenInView(child);
Expand Down Expand Up @@ -344,7 +344,7 @@ export const toggleTemporalConfidence = (): AnyAction => ({
/**
* restore original state by iterating over all nodes and restoring children to unexplodedChildren (as necessary)
*/
const _resetExpodedTree = (nodes: ReduxNode[]): void => {
const _resetExpodedTree = (nodes: ReduxNodeBase[]): void => {
nodes.forEach((n) => {
if (Object.prototype.hasOwnProperty.call(n, 'unexplodedChildren')) {
n.children = n.unexplodedChildren;
Expand All @@ -365,10 +365,10 @@ const _resetExpodedTree = (nodes: ReduxNode[]): void => {
*/
const _traverseAndCreateSubtrees = (
/** root node of entire tree */
root: ReduxNode,
root: ReduxNodeBase,

/** current node being traversed */
node: ReduxNode,
node: ReduxNodeBase,

/** trait name to determine if a child should become subtree */
attr: string,
Expand Down Expand Up @@ -410,7 +410,7 @@ const _traverseAndCreateSubtrees = (
*/
const _orderSubtrees = (
metadata: Metadata,
nodes: ReduxNode[],
nodes: ReduxNodeBase[],
attr: string,
): void => {
const attrValueOrder = getLegendOrder(attr, metadata.colorings[attr], nodes, undefined);
Expand Down
58 changes: 29 additions & 29 deletions src/components/tree/phyloTree/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { getBranchVisibility, strokeForBranch } from "./renderers";
import { Layout, shouldDisplayTemporalConfidence } from "../../../reducers/controls";
import { Visibility } from "../../../reducers/tree";
import { makeTipLabelFunc } from "./labels";
import { Distance, PhyloNode, PhyloTree, PropsForPhyloNodes, SVGProperty, TreeElement } from "./types";
import { Distance, PhyloNodeBase, PhyloTreeBase, PropsForPhyloNodes, SVGProperty, TreeElement } from "./types";

/* loop through the nodes and update each provided prop with the new value
* additionally, set d.update -> whether or not the node props changed
*/
const updateNodesWithNewData = (
nodes: PhyloNode[],
nodes: PhyloNodeBase[],
newNodeProps: PropsForPhyloNodes,
): void => {
// console.log("update nodes with data for these keys:", Object.keys(newNodeProps));
Expand All @@ -41,34 +41,34 @@ const updateNodesWithNewData = (
const svgSetters = {
attrs: {
".tip": {
r: (d: PhyloNode) => d.r,
cx: (d: PhyloNode) => d.xTip,
cy: (d: PhyloNode) => d.yTip
r: (d: PhyloNodeBase) => d.r,
cx: (d: PhyloNodeBase) => d.xTip,
cy: (d: PhyloNodeBase) => d.yTip
},
".branch": {
},
".vaccineCross": {
d: (d: PhyloNode) => d.vaccineCross
d: (d: PhyloNodeBase) => d.vaccineCross
},
".conf": {
d: (d: PhyloNode) => d.confLine
d: (d: PhyloNodeBase) => d.confLine
}
},
styles: {
".tip": {
fill: (d: PhyloNode) => d.fill,
stroke: (d: PhyloNode) => d.tipStroke,
visibility: (d: PhyloNode) => d.visibility === NODE_VISIBLE ? "visible" : "hidden"
fill: (d: PhyloNodeBase) => d.fill,
stroke: (d: PhyloNodeBase) => d.tipStroke,
visibility: (d: PhyloNodeBase) => d.visibility === NODE_VISIBLE ? "visible" : "hidden"
},
".conf": {
stroke: (d: PhyloNode) => d.branchStroke,
stroke: (d: PhyloNodeBase) => d.branchStroke,
"stroke-width": calcConfidenceWidth
},
// only allow stroke to be set on individual branches
".branch": {
"stroke-width": (d: PhyloNode) => d["stroke-width"] + "px", // style - as per drawBranches()
stroke: (d: PhyloNode) => strokeForBranch(d), // TODO: revisit if we bring back SVG gradients
cursor: (d: PhyloNode) => d.visibility === NODE_VISIBLE ? "pointer" : "default",
"stroke-width": (d: PhyloNodeBase) => d["stroke-width"] + "px", // style - as per drawBranches()
stroke: (d: PhyloNodeBase) => strokeForBranch(d), // TODO: revisit if we bring back SVG gradients
cursor: (d: PhyloNodeBase) => d.visibility === NODE_VISIBLE ? "pointer" : "default",
visibility: getBranchVisibility
}
}
Expand All @@ -86,8 +86,8 @@ function createUpdateCall(

/** e.g. ["visibility", "stroke-width"] */
properties: Set<SVGProperty>,
): (selection: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => void {
return (selection: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => {
): (selection: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => void {
return (selection: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => {
// First: the properties to update via d3Selection.attr call
if (svgSetters.attrs[treeElem]) {
[...properties].filter((x) => svgSetters.attrs[treeElem][x])
Expand All @@ -110,12 +110,12 @@ function createUpdateCall(
const genericSelectAndModify = (
svg: Selection<SVGSVGElement | null, unknown, null, any>,
treeElem: TreeElement,
updateCall: (transition: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => void,
updateCall: (transition: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => void,
transitionTime: number,
): void => {
// console.log("general svg update for", treeElem);
svg.selectAll<SVGGElement, PhyloNode>(treeElem)
.filter((d: PhyloNode) => !!d.update)
svg.selectAll<SVGGElement, PhyloNodeBase>(treeElem)
.filter((d: PhyloNodeBase) => !!d.update)
.transition().duration(transitionTime)
.call(updateCall);
if (!transitionTime) {
Expand All @@ -132,13 +132,13 @@ const genericSelectAndModify = (
* @extras {dict} - extra keywords to tell this function to call certain phyloTree update methods. In flux.
*/
export const modifySVG = function modifySVG(
this: PhyloTree,
this: PhyloTreeBase,
elemsToUpdate: Set<TreeElement>,
svgPropsToUpdate: Set<SVGProperty>,
transitionTime: number,
extras: Extras,
): void {
let updateCall: (selection: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => void;
let updateCall: (selection: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => void;
const classesToPotentiallyUpdate: TreeElement[] = [".tip", ".vaccineDottedLine", ".vaccineCross", ".branch"]; /* order is respected */
/* treat stem / branch specially, but use these to replace a normal .branch call if that's also to be applied */
if (elemsToUpdate.has(".branch.S") || elemsToUpdate.has(".branch.T")) {
Expand All @@ -148,12 +148,12 @@ export const modifySVG = function modifySVG(
ST.forEach((x, STidx) => {
if (elemsToUpdate.has(`.branch${x}`)) {
if (applyBranchPropsAlso) {
updateCall = (selection: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => {
updateCall = (selection: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => {
createUpdateCall(".branch", svgPropsToUpdate)(selection); /* the "normal" branch changes to apply */
selection.attr("d", (d) => d.branch[STidx]); /* change the path (differs between .S and .T) */
};
} else {
updateCall = (selection: Transition<SVGGElement, PhyloNode, SVGSVGElement, unknown>) => {
updateCall = (selection: Transition<SVGGElement, PhyloNodeBase, SVGSVGElement, unknown>) => {
selection.attr("d", (d) => d.branch[STidx]);
};
}
Expand Down Expand Up @@ -221,7 +221,7 @@ export const modifySVG = function modifySVG(
* step 3: when step 2 has finished, redraw everything. No transition here.
*/
export const modifySVGInStages = function modifySVGInStages(
this: PhyloTree,
this: PhyloTreeBase,
elemsToUpdate: Set<TreeElement>,
svgPropsToUpdate: Set<SVGProperty>,
transitionTimeFadeOut: number,
Expand Down Expand Up @@ -278,7 +278,7 @@ export interface ChangeParams {
changeBranchThickness?: boolean
showConfidences?: boolean
removeConfidences?: boolean
zoomIntoClade?: false | PhyloNode
zoomIntoClade?: false | PhyloNodeBase
svgHasChangedDimensions?: boolean
animationInProgress?: boolean
changeNodeOrder?: boolean
Expand Down Expand Up @@ -310,7 +310,7 @@ interface Extras {
hideTipLabels?: boolean
}

export const change = function change(this: PhyloTree, params: ChangeParams): void {
export const change = function change(this: PhyloTreeBase, params: ChangeParams): void {
const {
/* booleans for what should be changed */
changeColorBy = false,
Expand Down Expand Up @@ -412,18 +412,18 @@ export const change = function change(this: PhyloTree, params: ChangeParams): vo
/* some things need to update d.inView and/or d.update. This should be centralised */
/* TODO: list all functions which modify these */
if (zoomIntoClade) { /* must happen below updateNodesWithNewData */
this.nodes.forEach((d: PhyloNode) => {
this.nodes.forEach((d: PhyloNodeBase) => {
d.inView = false;
d.update = true;
});
/* if clade is terminal, use the parent as the zoom node */
this.zoomNode = zoomIntoClade.n.hasChildren ?
zoomIntoClade :
zoomIntoClade.n.parent.shell;
applyToChildren(this.zoomNode, (d: PhyloNode) => {d.inView = true;});
applyToChildren(this.zoomNode, (d: PhyloNodeBase) => {d.inView = true;});
}
if (svgHasChangedDimensions || changeNodeOrder) {
this.nodes.forEach((d: PhyloNode) => {d.update = true;});
this.nodes.forEach((d: PhyloNodeBase) => {d.update = true;});
}

/* run calculations as needed - these update properties on the phylotreeNodes (similar to updateNodesWithNewData) */
Expand Down
36 changes: 18 additions & 18 deletions src/components/tree/phyloTree/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { max } from "d3-array";
import {getTraitFromNode, getDivFromNode, getBranchMutations} from "../../../util/treeMiscHelpers";
import { NODE_VISIBLE } from "../../../util/globals";
import { timerStart, timerEnd } from "../../../util/perf";
import { ReduxNode } from "../../../reducers/tree";
import { Distance, PhyloNode } from "./types";
import { ReduxNodeBase } from "../../../reducers/tree";
import { Distance, PhyloNodeBase } from "./types";

/** get a string to be used as the DOM element ID
* Note that this cannot have any "special" characters
Expand All @@ -23,10 +23,10 @@ export const getDomId = (
* to all child nodes, including internal nodes
*/
export const applyToChildren = (
phyloNode: PhyloNode,
phyloNode: PhyloNodeBase,

/** function to apply to each child. Is passed a single argument, the <PhyloNode> of the children. */
func: (node: PhyloNode) => void,
func: (node: PhyloNodeBase) => void,
): void => {
func(phyloNode);
const node = phyloNode.n;
Expand All @@ -46,8 +46,8 @@ export const applyToChildren = (
* Returns the current yCounter after assignment to the tree originating from `node`
*/
export const setDisplayOrderRecursively = (
node: PhyloNode,
incrementer: (node: PhyloNode) => number,
node: PhyloNodeBase,
incrementer: (node: PhyloNodeBase) => number,
yCounter?: number,
): number | undefined => {
const children = node.n.children; // (redux) tree node
Expand Down Expand Up @@ -100,7 +100,7 @@ export const setDisplayOrder = ({
nodes,
focus,
}: {
nodes: PhyloNode[]
nodes: PhyloNodeBase[]
focus: boolean
}): void => {
timerStart("setDisplayOrder");
Expand Down Expand Up @@ -170,7 +170,7 @@ export const formatDivergence = (divergence: number): string | number => {
* This differs depending on which tree is in view so it's helpful to access it
* by reaching into phyotree to get it
*/
export const getIdxOfInViewRootNode = (node: ReduxNode): number => {
export const getIdxOfInViewRootNode = (node: ReduxNodeBase): number => {
return node.shell.that.zoomNode.n.arrayIdx;
};

Expand All @@ -179,8 +179,8 @@ export const getIdxOfInViewRootNode = (node: ReduxNode): number => {
* NOTE: `otherNode` is always closer to the root in the tree than `node`
*/
function isWithinBranchTolerance(
node: ReduxNode,
otherNode: ReduxNode,
node: ReduxNodeBase,
otherNode: ReduxNodeBase,
distanceMeasure: Distance,
) {
if (distanceMeasure === "num_date") {
Expand All @@ -201,7 +201,7 @@ function isWithinBranchTolerance(
* Walk up the tree from node until we find either a node which has a nucleotide mutation or we
* reach the root of the (sub)tree. Gaps, deletions and undeletions do not count as mutations here.
*/
function findFirstBranchWithAMutation(node: ReduxNode): ReduxNode {
function findFirstBranchWithAMutation(node: ReduxNodeBase): ReduxNodeBase {
if (node.parent === node) {
return node;
}
Expand All @@ -220,10 +220,10 @@ function findFirstBranchWithAMutation(node: ReduxNode): ReduxNode {
* the tree (and distanceMeasure=div) then we find the first branch with a mutation.
*/
export const getParentBeyondPolytomy = (
node: ReduxNode,
node: ReduxNodeBase,
distanceMeasure: Distance,
observedMutations: Record<string, number>,
): ReduxNode => {
): ReduxNodeBase => {
let potentialNode = node.parent;
if (distanceMeasure==="div" && areNucleotideMutationsPresent(observedMutations)) {
return findFirstBranchWithAMutation(node);
Expand Down Expand Up @@ -263,14 +263,14 @@ export function guessAreMutationsPerSite(
* Is the node a subtree root node? (implies that we have either exploded trees or
* the dataset has multiple subtrees to display)
*/
const isSubtreeRoot = (n: ReduxNode): boolean => (n.parent.name === "__ROOT" && n.parentInfo.original !== undefined);
const isSubtreeRoot = (n: ReduxNodeBase): boolean => (n.parent.name === "__ROOT" && n.parentInfo.original !== undefined);

/**
* Gets the parent node to be used for stem / branch calculation.
* Most of the time this is the same as `d.n.parent` however it is not in the
* case of the root nodes for subtrees (e.g. exploded trees).
*/
export const stemParent = (n: ReduxNode): ReduxNode => {
export const stemParent = (n: ReduxNodeBase): ReduxNodeBase => {
return isSubtreeRoot(n) ? n.parentInfo.original : n.parent;
};

Expand All @@ -282,11 +282,11 @@ export const stemParent = (n: ReduxNode): ReduxNode => {
* whereas the rectangular tree renders zero at the top and goes downwards
*/
export const nodeOrdering = (
nodes: PhyloNode[],
): ((d: PhyloNode) => [number, number]) => {
nodes: PhyloNodeBase[],
): ((d: PhyloNodeBase) => [number, number]) => {
const maxVal = nodes.map((d) => d.displayOrder)
.reduce((acc, val) => ((val ?? 0) > acc ? val : acc), 0);
return (d: PhyloNode) => ([
return (d: PhyloNodeBase) => ([
maxVal - d.displayOrder,
isSubtreeRoot(d.n) ? undefined : (maxVal - d.n.parent.shell.displayOrder)
]);
Expand Down
Loading

0 comments on commit 12aff24

Please sign in to comment.