// Type definitions for phylotree // Project: https://github.com/veg/phylotree.js import { HierarchyNode, HierarchyLink } from 'd3-hierarchy'; /** * Node data stored in the phylogenetic tree */ export interface PhylotreeNodeData { name: string; attribute?: string; annotation?: string; [key: string]: any; } /** * A node in the phylogenetic tree (D3 hierarchy node with phylotree data) */ export type PhylotreeNode = HierarchyNode & { selected?: boolean; tag?: boolean; collapsed?: boolean; hidden?: boolean; notshown?: boolean; screen_x?: number; screen_y?: number; text_angle?: number; text_align?: string; angle?: number; radius?: number; }; /** * A link/branch in the phylogenetic tree */ export type PhylotreeLink = HierarchyLink & { source: PhylotreeNode; target: PhylotreeNode; }; /** * Options for rendering a phylogenetic tree */ export interface RenderOptions { /** CSS selector or DOM element for the container */ container?: string | HTMLElement; /** Width of the SVG in pixels */ width?: number; /** Height of the SVG in pixels */ height?: number; /** Enable zoom/pan behavior */ zoom?: boolean; /** Tree layout: "left-to-right" or "right-to-left" */ layout?: 'left-to-right' | 'right-to-left'; /** Use radial/circular layout */ 'is-radial'?: boolean; /** Use unrooted (equal-angle) layout */ 'is-unrooted'?: boolean; /** Align tip labels */ 'align-tips'?: boolean; /** Show node labels */ 'show-labels'?: boolean; /** Show scale bar */ 'show-scale'?: boolean; /** Draw size bubbles on nodes */ 'draw-size-bubbles'?: boolean; /** Show internal node names */ 'internal-names'?: boolean | ((node: PhylotreeNode) => boolean); /** Enable node selection */ selectable?: boolean; /** Enable collapsing of clades */ collapsible?: boolean; /** Enable brushing for selection */ brush?: boolean; /** Left offset in pixels */ 'left-offset'?: number; /** Spacing mode for top-bottom */ 'top-bottom-spacing'?: 'fixed-step' | 'fit'; /** Spacing mode for left-right */ 'left-right-spacing'?: 'fixed-step' | 'fit'; /** Font size for labels */ 'font-size'?: number; /** Maximum label width in characters */ 'max-label-width'?: number; /** Bubble styler function */ 'bubble-styler'?: (node: PhylotreeNode) => number; /** Restrict which nodes can be selected */ 'restricted-selectable'?: string | ((link: PhylotreeLink) => boolean); /** Logger instance */ logger?: Console; } /** * Options for parsing tree input */ export interface ParseOptions { /** Enable bootstrap value parsing */ bootstrap_values?: boolean; /** Format type: "newick", "phyloxml", "nexus" */ type?: string | ((input: string, options: ParseOptions) => any); /** Logger instance */ logger?: Console; } /** * The TreeRender class handles visualization of the tree */ export class TreeRender { /** The phylotree instance this renderer belongs to */ phylotree: Phylotree; /** The SVG element */ svg: d3.Selection; /** Rendering options */ options: RenderOptions; /** Current zoom transform */ currentZoomTransform: d3.ZoomTransform | null; /** Label width in pixels */ label_width: number; /** Rightmost leaf x position */ right_most_leaf: number; /** The container element */ container: string | HTMLElement; constructor(phylotree: Phylotree, options?: RenderOptions); /** Get the SVG element */ show(): SVGSVGElement; /** Update the tree display */ update(): this; /** Update layout coordinates */ update_layout(tree: PhylotreeNode): this; /** Get/set radial mode */ radial(value?: boolean): boolean | this; /** Get/set unrooted (equal-angle) layout mode */ unrooted(value?: boolean): boolean | this; /** Get/set align tips mode */ alignTips(value?: boolean): boolean | this; /** Get/set selection label */ selectionLabel(label?: string): string | this; /** Get/set node label accessor */ nodeLabel(accessor?: (node: PhylotreeNode) => string): ((node: PhylotreeNode) => string) | this; /** Get/set node styler function */ nodeStyler(styler?: (element: d3.Selection, node: PhylotreeNode) => void): this; /** Get/set edge styler function */ edgeStyler(styler?: (element: d3.Selection, link: PhylotreeLink) => void): this; /** Collapse a node */ collapse_node(node: PhylotreeNode): this; /** Modify selection based on a callback */ modifySelection(callback: (link: PhylotreeLink, callback: (selected: boolean) => void) => boolean): this; /** Get selected nodes */ getSelection(): PhylotreeNode[]; /** Get selected branches */ getSelectedBranches(): PhylotreeLink[]; /** Register event listener */ on(event: string, callback: (...args: any[]) => void): this; /** Emit an event */ emit(event: string, ...args: any[]): this; /** Selection callback setter */ selectionCallback(callback: (selection: PhylotreeNode[]) => void): this; /** * Get or set spacing in the x-direction (horizontal spacing between nodes) * @param attr The new spacing value if setting * @param skip_render Whether to skip re-rendering after setting * @returns The current spacing_x value if getting, or the TreeRender instance if setting */ spacing_x(): number; spacing_x(attr: number, skip_render?: boolean): this; /** * Get or set spacing in the y-direction (vertical spacing between levels) * @param attr The new spacing value if setting * @param skip_render Whether to skip re-rendering after setting * @returns The current spacing_y value if getting, or the TreeRender instance if setting */ spacing_y(): number; spacing_y(attr: number, skip_render?: boolean): this; /** * Get or set the font size for labels * @param attr The new font size if setting * @returns The current font size if getting, or the TreeRender instance if setting */ font_size(): number; font_size(attr: number): this; /** * Get or set the scale bar font size * @param attr The new font size if setting * @returns The current scale bar font size if getting, or the TreeRender instance if setting */ scale_bar_font_size(): number; scale_bar_font_size(attr: number): this; /** * Get or set the node circle size * @param attr The new circle size if setting * @param attr2 Optional second parameter * @returns The current node circle size if getting, or the TreeRender instance if setting */ node_circle_size(): number; node_circle_size(attr: number, attr2?: number): this; /** * Get or set CSS classes * @param opt CSS class options * @returns The current CSS classes if getting, or the TreeRender instance if setting */ css(): { [key: string]: string }; css(opt: { [key: string]: string }): this; /** * Get or set transitions * @param arg Transition settings * @returns The current transition settings if getting, or the TreeRender instance if setting */ transitions(): boolean | null; transitions(arg: boolean): this; /** * Layout the tree * @param transitions Whether to use transitions * @returns The TreeRender instance */ layout(transitions?: boolean): this; /** Refresh the tree display */ refresh(): this; /** Place nodes in the layout */ placenodes(): this; /** * Set the separation function for node spacing * @param callback Function that returns additional spacing between nodes * @returns The TreeRender instance */ separation(callback: (node: PhylotreeNode, previous: PhylotreeNode) => number): this; /** * Set internal node labels based on children * @param callback Function that determines label based on children * @param respect_existing Whether to respect existing selections * @returns The TreeRender instance */ internalLabel(callback: (children: PhylotreeNode[]) => boolean, respect_existing?: boolean): this; /** * Get or set the count handler callback * @param callback Function called with selection count * @returns The current handler if getting, or the TreeRender instance if setting */ countHandler(): ((count: number) => void) | null; countHandler(callback: (count: number) => void): this; /** * Update the selection key name * @param old_key The old key name * @param new_key The new key name * @returns The TreeRender instance */ updateKeyName(old_key: string, new_key: string | null): this; /** * Set the size of the tree display * @param attr Size as [width, height] * @returns The current size if getting, or the TreeRender instance if setting */ set_size(): [number, number]; set_size(attr: [number, number]): this; } /** * Main Phylotree class for creating and manipulating phylogenetic trees */ export class phylotree { /** Hierarchical tree structure (D3 hierarchy) */ nodes: PhylotreeNode; /** Links between nodes */ links: PhylotreeLink[]; /** Parsed annotation tags */ parsed_tags: string[]; /** The tree renderer (set after calling render()) */ display: TreeRender | null; /** Original Newick string */ newick_string: string; /** Selection attribute name */ selection_attribute_name: string; /** * Create a new phylogenetic tree * @param nwk Newick string, PhyloXML string, or hierarchical JSON * @param options Parsing options */ constructor(nwk: string | object, options?: ParseOptions); /** * Render the tree to an SVG * @param options Rendering options * @returns TreeRender instance */ render(options?: RenderOptions): TreeRender; /** * Traverse the tree and compute values at each node * @param callback Function called on each node * @param traversal_type "pre-order", "post-order", or "in-order" * @param root_node Optional starting node * @param backtrack Optional function to stop traversal */ traverse_and_compute( callback: (node: PhylotreeNode) => void, traversal_type?: 'pre-order' | 'post-order' | 'in-order', root_node?: PhylotreeNode, backtrack?: (node: PhylotreeNode) => boolean ): void; /** Export tree to JSON string */ json(traversal_type?: string): string; /** Get parsed annotation tags */ get_parsed_tags(): string[]; /** Update tree from JSON */ update(json: object): this; /** Check if tree has branch lengths */ hasBranchLengths(): boolean; /** Get all branch lengths */ getBranchLengths(): number[]; /** Set branch length accessor */ setBranchLength(accessor: (node: PhylotreeNode) => number): this; /** Normalize branch lengths */ normalizeBranchLengths(attr?: string): this; /** Scale branch lengths by a factor */ scaleBranchLengths(scale: number): this; /** Get branch name accessor */ branchName(accessor?: (node: PhylotreeNode) => string): string | this; /** Get Newick representation of tree */ getNewick(annotator?: (node: PhylotreeNode) => string): string; /** Get tagged Newick representation */ getTaggedNewick(): string; /** Find most recent common ancestor of nodes */ mrca(nodes: (PhylotreeNode | string)[]): PhylotreeNode; /** Check if a node is a leaf */ isLeafNode(node: PhylotreeNode): boolean; /** Get all tip/leaf nodes */ getTips(): PhylotreeNode[]; /** Get all internal nodes */ getInternals(): PhylotreeNode[]; /** Get root node */ getRootNode(): PhylotreeNode; /** Get all nodes */ getNodes(): PhylotreeNode[]; /** Get node by name */ getNodeByName(name: string): PhylotreeNode | undefined; /** Select all descendants of a node */ selectAllDescendants(node: PhylotreeNode, terminal?: boolean, internal?: boolean): PhylotreeNode[]; /** Reroot the tree at a node */ reroot(node: PhylotreeNode, fraction?: number): this; /** Get path from a node to the root */ pathToRoot(node: PhylotreeNode): PhylotreeNode[]; /** Resort children of nodes */ resortChildren(comparator: (a: PhylotreeNode, b: PhylotreeNode) => number): this; /** Graft a new node */ graftANode(graftAt: PhylotreeNode, newChild: PhylotreeNode, newParent?: PhylotreeNode, lengths?: { new_child: number; new_parent: number }): void; /** Add a child node */ addChild(parent: PhylotreeNode, child: PhylotreeNode): void; /** Delete a node */ deleteANode(index: number): void; /** Assign attributes to nodes */ assignAttributes(attributes: object): this; /** Get tip lengths for date extraction */ getTipLengths(): { [name: string]: number }; /** Maximum parsimony ancestral state reconstruction */ maxParsimony(attr: string, states: string[]): this; /** Clear internal node selections */ clearInternalNodes(respect?: boolean): this; } // Utility functions /** * Parse a Newick format string */ export function newickParser(newick: string, options?: ParseOptions): { json: object; error: string | null }; /** * Get Newick string from tree */ export function getNewick(tree: PhylotreeNode, annotator?: (node: PhylotreeNode) => string): string; /** * Compute pairwise distances between nodes */ export function pairwise_distances(tree: phylotree): number[][]; /** * Compute pairwise distances between nodes (camelCase alias) */ export function pairwiseDistances(tree: phylotree): number[][]; /** * Compute Sackin's index (tree balance measure) */ export function sackin(tree: phylotree): number; /** * Find center of tree */ export function centerOfTree(tree: phylotree): PhylotreeNode; /** * Compute midpoint for rooting */ export function computeMidpoint(tree: phylotree): { node: PhylotreeNode; fraction: number }; /** * Root to tip regression */ export function rootToTip(tree: phylotree, attr?: string): { slope: number; intercept: number; r2: number; data: Array<{ date: number; distance: number; name: string }>; }; /** * Fit root to tip (find optimal root) */ export function fitRootToTip(tree: phylotree, attr?: string): { node: PhylotreeNode; fraction: number; r2: number; }; /** * Extract dates from tip names */ export function extract_dates(tree: phylotree, pattern?: RegExp): { [name: string]: number }; /** * Extract dates from tip names (camelCase alias) */ export function extractDates(tree: phylotree, pattern?: RegExp): { [name: string]: number }; /** * Cluster Picker algorithm */ export function clusterPicker(tree: phylotree, options?: { bootstrap_threshold?: number; distance_threshold?: number; }): PhylotreeNode[][]; /** * PhyloPart clustering algorithm */ export function phylopart(tree: phylotree, options?: { bootstrap_threshold?: number; }): PhylotreeNode[][]; /** * Parse FASTA format */ export function parseFasta(fasta: string): Array<{ name: string; seq: string }>; /** * Neighbor joining tree construction */ export function neighborJoining(matrix: number[][], labels: string[]): object; /** * Get distance matrix from sequences */ export function getDistanceMatrix(sequences: Array<{ name: string; seq: string }>): { matrix: number[][]; labels: string[]; }; /** * Load annotations from NEXUS file */ export function loadAnnotations(nexus: string): object; /** * Parse annotations from NEXUS */ export function parseAnnotations(nexus: string): object; // Tree traversal functions /** * In-order traversal */ export function inOrder(node: PhylotreeNode, callback: (node: PhylotreeNode) => void, backtrack?: (node: PhylotreeNode) => boolean): void; /** * Pre-order traversal */ export function preOrder(node: PhylotreeNode, callback: (node: PhylotreeNode) => void, backtrack?: (node: PhylotreeNode) => boolean): void; /** * Post-order traversal */ export function postOrder(node: PhylotreeNode, callback: (node: PhylotreeNode) => void, backtrack?: (node: PhylotreeNode) => boolean): void; /** * Left-child right-sibling traversal */ export function leftChildRightSibling(node: PhylotreeNode, callback: (node: PhylotreeNode) => void): void;