tnt.tree creates a new tree visualisation. There are several components that need to be set up in this visualisation. One is the tree object to display. You can obtain a valid tree object directly from newick or nhx formats through tnt.tree.parse_newick or tnt.tree.parse_nhx respectively, or you can pass a javascript object with a tree structure as shown below. Once loaded TnT Tree offers several methods to manipulate the tree as shown below in the Node API. For example:
In the snippet above, a new tree visualisation is created using tnt.tree() and using the shown newick tree as its data. The root of the tree is then retrieved from the visualisation. At this point it is possible to update this tree with the methods explained below. It is important to realise that the tree is not rendered until the visualisation is executed using a DOM container as its argument (line 5 in the snippet above).
New trees visualisations can be created using the tnt.tree method. The returned tree visualisation is configurable via the methods explained below. An example of use looks like:
# tnt.tree ()
Creates a new tree visualization that can be configured using the methods explained below. The returned visualisation is a function itself that can be called passing a DOM element as its argument and is used as a container for the visualization. The tree is only rendered when the visualisation is called.
# tree.data (<object>)
Sets the data to be used in the tree visualization (the tree). This tree needs to be a tree like structure in JSON format like the one shown below. This JSON object can be obtained with tnt.tree.parse_json or tnt.tree.parse_nhx
# tree.duration (<integer>)
Specifies the duration of the transitions when the tree is udpated. If no argument is provided it returns the current duration. By default this value is 750 ms.
# tree.update ()
Updates the tree visualisation. This means that the visualisation is re-initialised using the current state. For example, if a change in the labels or the node's display is performed, the changes are not rendered until this method is called.
# tree.update_nodes ()
Updates the node display and labels of the tree visualisation. The main difference with the update method is that update_nodes doesn't recompute the tree layout and only a more performant update of the aspect of nodes and labels are performed.
# tree.on. (<string, callback>)
Adds an event listener to each node in the tree visualisation. Its first argument is a string with the event name. click, dblclick, mouseover and mouseout are accepted. The second argument is a callback that receives the clicked node as its argument and is executed when the event is fired.
# tree.root (<tnt.tree.node>)
Gets the root node of the tree used in the visualization. This method can not be used to re-root a tree with an internal node.
# tree.scale_bar (<number, string>)
Retrieves the scale value for a given number of pixels or tree units. It accepts two arguments, the first one specifies the value to scale, the second specifies the input units (either "pixel" or "tree"). For example passing 50, "pixel" returns the number in tree units corresponding to that pixel length, while passing 0.1, "tree" returns the number of pixels that a branch of length 0.1 would take in the final tree display. If the tree doesn't specify branch lenghts the method returns undefined.
# tree.branch_color (<string | callback>)
Specifies the color of the branches in the tree. This color can be given as a string name (like "blue") or its hexadecimal code (like '#00FF00'). To get per branch colors use a callback instead. This callback will be called on each branch with the source and destination nodes as arguments. By default branches are displayed black. If called without arguments the current value is returned.
TnT Tree provides several methods for tree manipulation, these include node searching, mapping callbacks to nodes, calculating the lowest common ancestor of a set of nodes or getting a subtree, for example. The root node of a tree can be obtained using the root method on the tree visualization. It is also possible to create new nodes from a tree data structure using the tnt.tree.node function. See below for an example.
# tnt.tree.node (<object>)
Creates a new TnT Tree Node from the JSON object provided as its argument. This object is expected to be a nested JSON with a children property whose value is an array of children nodes. tnt.tree.parse_newick and tnt.tree.parse_nhx returns an object of these characteristics.
# node.data (<object>)
sets a new tree JSON object in the current node. If called without arguments returns the current tree data object. This method can not be used to first set the data for a node (see the example below)
# node.find_node (<callbak, boolean>)
Retrieves a node based on a given condition. This method accepts two parameters. The first one is a callback that is called on every node of the tree. This callback is expected to accept a node as its argument and return true or false. The method returns the first node for which the condition is true. Use node.find_all to get all the nodes satisfying the condition. The second argument is a boolean indicating if collapsed branches should be traversed or not. By default this option is false so collapsed branches are ignored.
# node.find_all (<callback, boolean>)
Retrieves all the nodes satisfying a given condition. This method accepts two parameters. The first one is a callback that is called on every node of the tree. This callback is expected to accept a node as its argument and return true or false. The method returns an array containing all the downstream nodes for which the condition is true. The second argument is a boolean indicating if collapsed branches should be traversed or not. By default this option is false so collapsed branches are ignored.
# node.find_node_by_name (<string, boolean>)
Retrieves a node based on its 'name' field. This is a specialised case of node.find_node. The first argument specifies the name of the node and the second is a boolean indicating if collapsed branches should be traversed or not (false by default)
# node.toggle ()
Toggles collapsibility of the current branch at the current node. If the current node is not collapsed, it becomes collapsed, if it is already collapsed, this method uncollapses it. The return value is the same node.
# node.is_collapsed ()
Returns true if the branch is collapsed at the current node and false otherwise. It also returns false when the node is not collapsed but any of its ancestors is.
# node.n_hidden ()
Returns the number of nodes under a collapsed node. This is, the number of nodes that would be hidden in the tree visualization if the node gets collapsed.
# node.lca (<Array>)
Returns the lowest common ancestor node of an array of nodes.
# node.get_all_nodes (<boolean>)
Returns an array containing all the nodes downstream the current node including itself. This means that if called on a leave it will still return one node (itself). This method accepts an optional boolean argument that specifies if the collapsed nodes should be also traversed or not. This argument is set to false by default
# node.get_all_leaves (<boolean>)
Returns an array with all the leaf nodes downstream by traversing all the tree. It accepts an optional boolean argument. If set to true the method also traverses collapsed nodes (false by default);
# node.upstream (<callback>)
Applies the passed callback to all the ancestors of the current node. This callback is called passing each ancestor node as its argument. The ancestors are passed in order until the root of the tree is reached (ie, the ancestor that doesn't have a parent).
# node.subtree (<Array, boolean>)
Returns the root node of a subtree that is built by getting the lowest common ancestor of the given nodes. Its first argument is an array of nodes. An optional second argument specifies if the subtree should keep singleton nodes (nodes with only one children). This argument is set to false by default meaning that singletons are filtered out in the subtree. The returned subtree is made by cloning the nodes nodes of the original tree, so changing one doesn't affect the other.
# node.flatten (<boolean>)
Recursively flattens all the downstream leaves of the current node. This means that when called on a node all the downstream leaf nodes attached directly to it. If called on a leaf, no action is made. By default, the intermediate (internal) nodes are discarded. It accepts an optional boolean value to keep them when set to true
# node.present (<callback>)
Returns true if any of the downstream nodes satisfied the passed condition or false otherwise. The condition is expected to be a callback that accepts a node as its argument and returns true or false.
# node.sort (<callback>)
Recursively sorts the children of each downstream node based on the given callback. This ordering does not affect the tree topology, it just reorders the children. The given callback is expected to receive a pair of nodes and return -1, 0 or 1 if the first node should be placed before the second, there is a tie or if the second should be placed before the first respectively.
# node.apply (<callback, boolean>)
Recursively applies the given callback to each downstream node of the current node. The node is passed to the callback as its argument. See node.sort for an example. This method also accepts a boolean as an optional second argument. If set to true also the collapsed nodes are visited. This option is set to false by default
# node.property (<string | callback, value>)
Accesses to data properties in the current node. The first parameter is mandatory and corresponds with the property to be accessed. If a second parameter is provided, the method sets the property with the given value, if it is not provided, it returns the value. If a callback is used as its first parameter, it is treated as a way to access the field (for example if it is a deeper field in the node structure). For example
# node.is_leaf (<boolean>)
Returns true if the current node is a leaf, false otherwise. An optional boolean argument can be passed to take into account collapsed nodes. For example
# node.node_name ()
Returns the _name_ property of the current node. It is an alias of node.property using 'name' as its value
# node.branch_length ()
Returns the branch length of the current node. If it is not set it returns undefined
# node.root_dist ()
Returns the distance of the current node to the root based on the branch lengths of the tree. Only the branch lengths up to the root node are considered, ie, if the root has a branch length itself, this is not included in the final result.
# node.children (<boolean>)
Returns an array with all the children nodes of the current node. This method accepts an optional boolean argument that if set to true makes this method to also return collapsed children
# node.parent ()
Returns the parent of the current node or undefined if called on the root of the tree.
The size, shape and color of the nodes are configurable by specifying the display of the nodes. There are different predefined shapes available in TnT Tree like circles, squares and triangles, but it is easy to build your own SVG shapes. The size of the nodes have an impact in the computed height of the tree when the vertical layout is used.
# tree.node_display (<tnt.tree.node_display>)
Specifies the shape, size and color of nodes of the tree visualisation. It accepts an argument of type tnt.tree.node_display. If called without arguments the current value is returned. By default black circles of size 4.5 pixels are displayed.
# [interface] tnt.tree.node_display ()
Defines the size, shape and color of the nodes in the tree visualisation. This is a general interface to create new node displays. TnT Tree offers some predefined displays for circles (tnt.tree.node_display.circle), squares (tnt.tree.node_display.square) or triangles (tnt.tree.node_display.triangle). Most of the time you want to use them, but it is possible to define other shapes using this general interface. For example, this is a simplified version of how circle nodes are defined in tnt.tree.node_display.circle
# [interface method] node_display.display (<callback>)
Defines how to render each node in the tree visualisation. The expected argument is a callback that is called on each node of the visualisation. Inside the argument, this is set to the g element where the node is rendered. If called without arguments, the current callback is returned. This callback is undefined in the general tnt.tree.node_display and defined in the specific node shapes for (circles or squares for example). See the Node displays section for an example.
# node_display.size (<integer | callback>)
Specifies the size of each node in the tree visualisation. The expected argument is an integer representing the size of the node in pixels. If called without arguments the currect value is returned. To obtain per node sizes use a callback instead. This callback is called on each node passing it as its argument. The node size has an impact in the total height of the trees with vertical layouts. The height of a node is calculated as the maximum height between its node's size and its label's height. The maximum height is calculated as the maximum height of all the nodes (in case that different nodes have different sizes).
# node_display.fill (<string | callback>)
Specifies the fill color of the nodes. This color can be given as a color name (like "blue") or its hexadecimal code (like "#00FF00"). To get per node colors use a callback instead. This callback is called on each node passing it as its argument. The default color for nodes is "black".
# node_display.stroke (<string | callback>)
Specifies the stroke color of each node. This color can be given as a color name ("red") or its hexadecimal code ("#FF0000"). To get per node stroke colors use a callback instead. This callback is called on each node passing it as its argument. The default stroke color is "black"
# node_display.stroke_width (<integer>)
Specifies the stroke with of each node. The expected argument is the stroke width in pixels. To get per node stroke widths use a callback instead. This callback is called on each node passing it as its argument. The default stroke-width is 1px
# tnt.tree.node_display.circle ()
Pre-defined circle shape for nodes. This display is based on the general node display interface, so all the methods described above for the general interface (fill, size<, stroke, etc) are also available in the circle display.
# tnt.tree.node_display.square ()
Pre-defined square shape for nodes. This display is based on the general node display interface, so all the methods described above for the general interface (fill, size<, stroke, etc) are also available in the square display.
# tnt.tree.node_display.triangle ()
Pre-defined square shape for nodes. This display is based on the general node display interface, so all the methods described above for the general interface (fill, size<, stroke, etc) are also available in the triangle display.
Specifies the labels of each node in the tree visualisation. The height of the labels also affects the space between nodes (and the total height of the tree in the vertical layout as explained in the layout section). See below for different examples
# tree.label (<tnt.tree.label>)
Specifies the label to be used in each node of the tree visualisation. Accepts an argument of type tnt.tree.label. Returns the current value if called without arguments. By default, a tnt.tree.label.text is used displaying the name field of the node.
# [interface] tnt.tree.label ()
Creates a new label for nodes. This is a general interface to create new labels. This label renderer is called on every node. TnT also offers pre-defined label displays for text and image labels.
# [interface method] label.display (<callback>)
Specifies how to render each label in the tree. It accepts a callback as its argument. This callback is called on each node passing it and the layout type (ie, "radial" or "vertical") as its arguments. If called without arguments, returns the current value.
# label.width (<integer>)
Specifies the width of each label in pixels. If called without arguments returns the current width.
# label.height (<integer>)
Specifies the height of each label in pixels. If called without arguments returns the current height. This value affects the total height of the tree if using a vertical layout.
# label.on. (<string, callback>)
Adds an event listener to each label. Its first argument is a string with the event name. click, dblclick, mouseover and mouseout are accepted event names. The second argument is a callback that receives the corresponding node (See node's on method) unless the same event listener is defined in the label.
# tnt.tree.label.text ()
Pre-defined text labels for nodes. This label is based on the general label interface and hence all the methods described above for the general interface are also available in the text label display. It also defines additional methods described below. In text labels, the width of the label is automatically set based on the defined fontsize (see below).
# text.fontsize (<integer | callback>)
Sets the fontsize of the text label. The font size is specified as an integer meaning the pixel size of the font. To get per label font sizes use a callback instead. This callback is called on each node passing it as its argument and is expected to return the font size (in pixels) for that label. If called without arguments the current value is returned.
# text.color (<string | callback>)
Specifies the color of the text label. This color can be given as a string specifying the name of the color (like "black") or its hexadecimal code (like '#000000'). To get per label colors use a callback instead. This callback is called on each node passing it as its argument and is expected to return the color for that label. The default color of the text labels is "black". If called without arguments, the current value (string or callback) is returned.
# text.text (<string | callback>)
Specifies the text to display in the text label. The argument can be a literal string or a callback. If the latter, the callback is called on each node passing it as its argument and is expected to return the text to display for that label. By default the name property of the node is used.
# tnt.tree.label.img ()
Pre-defined image labels for nodes. This label is based on the general tnt.tree.label interface and hence has the same methods described above for general labels plus some specific methods described below.
# img.src (<callback>)
Specifies the path where the image labels are located. The argument is a callback that is called on each node passing it as its argument. If called without arguments the current value is returned.
# tnt.tree.label.composite ()
Returns a label made of two or more simple labels. The total width of the composite label is the sum of widths of the individual labels (plus a fixed offset) while its height is set to the maximum height of the individual labels.
# label.composite.add_label (<tnt.tree.label>)
Adds a new simple label to the composite label. The order of the added labels is important because the new labels are moved right to accommodate previous ones
The layout specifies the general shape of the tree. Currently TnT Tree supports two types of layouts, vertical and radial. Both have a common set of methods that control different aspects, for example the width of vertical trees and the diameter for radial trees. In the case of vertical trees, the height is calculated dynamically based on the maximum leaf height multiplied by the number of leaves. For each leaf, its height is calculated as the maximum value between the nodes height and the label height (see tnt.tree.label and tnt.tree.node_display).
# tree.layout (<tnt.tree.layout>)
Specifies the layout to be used in the tree visualization. Accepts an optional argument of type tnt.tree.layout. If called without arguments returns the current value.
# [interface] tnt.tree.layout.layout ()
Specifies a layout for the tree visualisation. This is a general interface for creating new layouts. It needs to be configured using the methods explained below. TnT Tree offers two pre-defined layouts ready to use, vertical and radial layouts.
# [interface method] layout.cluster (<d3.layout.cluster>)
# [interface method] layout.yscale (<integer array>)
# [interface method] layout.adjust_cluster_size (<callback>)
# [interface method] layout.height (<callback>)
# layout.scale (<boolean>)
Specifies if the branches should be scaled based on the tree's branch lengths (true) or not (false) (true by default). If called without arguments, returns the current scale value.
# layout.width (<scalar>)
Specifies the width of the tree layout in pixels. If called without arguments returns the current width.
# tnt.tree.layout.vertical ()
Returns a vertical layout. This layout is based on the general layout interface, so it has all the methods explained above for for the general interface.
# tnt.tree.layout.radial ()
Returns a radial layout. This layout is based on the general layout interface, so it has all the methods explained above for for the general interface.
TnT Tree offers two methods to parse newick and nhx formatted trees into JSON objects. See below for a description of these methods and examples of usage.
# tnt.tree.parse_newick (<string>)
Parses newick formatted trees. This method returns a nested JSON object that can be passed directly to a tree visualisation using its data method.
# tnt.tree.parse_nhx (<string>)
Parses nhx formatted trees. This method returns a nested JSON object that can be passed directly to a tree visualisation using its data method.