heatmap-cluster
Version:
The Unipept visualisation library
115 lines (90 loc) • 3.21 kB
text/typescript
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;
}
}