UNPKG

heatmap-cluster

Version:
115 lines (90 loc) 3.21 kB
import ClusterElement from "./ClusterElement"; export default class TreeNode { private _leftChild: TreeNode | null; private _rightChild: TreeNode | null; private _parent: TreeNode | null; public readonly values: ClusterElement[]; public readonly height: number; // Keep track of which ID's are already assigned to TreeNode's. public static currentID = 0; // ID used for constructing graphs. public readonly id: number; constructor(parent: TreeNode | null, leftChild: TreeNode | null, rightChild: TreeNode | null, values: ClusterElement[], height: number) { this._parent = parent; this._leftChild = leftChild; this._rightChild = rightChild; this.values = values; this.height = height; this.id = TreeNode.currentID; TreeNode.currentID++; } get parent(): TreeNode | null { return this._parent; } set parent(value: TreeNode | null) { this._parent = value; } get leftChild(): TreeNode | null { return this._leftChild; } set leftChild(value: TreeNode | null) { this._leftChild = value; } get rightChild(): TreeNode | null { return this._rightChild; } set rightChild(value: TreeNode | null) { this._rightChild = value; } /** * Convert this tree and all of it's children to the Newic-format. * * @param: idExtractor Function that extract's the name from a given node's id. */ public toNewick(nameExtractor: (id: number) => string): string { let output: string = ""; if (!this.leftChild && !this.rightChild) { return nameExtractor(this.values[0].id) + ":" + this.height; } output += "("; if (this.leftChild) { output += this.leftChild.toNewick(nameExtractor) + ","; } if (this.rightChild) { output += this.rightChild.toNewick(nameExtractor); } output += ")" + this.id + ":" + this.height; return output; } /** * Convert this tree and all of it's children to the dot GraphViz-format. */ public toGraphViz(nameExtractor: (id: number) => string): string { let root: TreeNode | undefined = this; let output = "digraph dendrogram {\n"; let labels = ""; let edges = ""; let toCheck: TreeNode[] = [root]; while (toCheck.length > 0) { root = toCheck.shift(); if (!root) { break; } if (!root.leftChild && !root.rightChild) { labels += ` ${root.id} [label="${nameExtractor(root.values[0].id)}"];\n`; } else { labels += ` ${root.id} [label="${root.id}"];\n`; } if (root.leftChild) { edges += ` ${root.id} -> ${root.leftChild.id};\n`; toCheck.push(root.leftChild); } if (root.rightChild) { edges += ` ${root.id} -> ${root.rightChild.id};\n`; toCheck.push(root.rightChild); } } output += labels + edges + "}"; return output; } }