skbio.tree.BPTree#
- class skbio.tree.BPTree(B, lengths=None, names=None, edges=None)[source]#
A balanced parentheses succinct data structure tree representation.
The basis for this implementation is the data structure described by Cordova and Navarro [1]. In some instances, some docstring text was copied verbatim from the manuscript. This does not implement the bucket-based trees.
A node in this data structure is represented by 2 bits, an open parenthesis and a close parenthesis. The implementation uses a NumPy uint8 type where an open parenthesis is a 1 and a close is a 0. In general, operations on this tree are best suited for passing in the opening parenthesis index, so for instance, if you’d like to use BPTree.is_tip to determine if a node is a leaf, the operation is defined only for using the opening parenthesis. At this time, there is some ambiguity over what methods can handle a closing parenthesis.
Node attributes, such as names, are stored external to this data structure.
The motivator for this data structure is pure performance both in space and time. As such, there is minimal sanity checking. It is advised to use this structure with care, and ideally within a framework which can assure sanity.
- Parameters:
- Barray of uint8
The parentheses bit array encoding the tree topology, where an open parenthesis is 1 and a close parenthesis is 0. A bool array is also accepted, and is viewed as uint8. It may belong to any array API backend (e.g., CuPy, PyTorch or JAX) and live on any device; see Notes.
- lengthsnumpy.ndarray of float64, optional
Branch length per parenthesis (read at opening parentheses). Defaults to 0.
- namesnumpy.ndarray of object, optional
Node name per parenthesis (read at opening parentheses). Defaults to None.
- edgesnumpy.ndarray of int32, optional
Edge number per parenthesis (read at opening parentheses). Defaults to 0, without an edge-number lookup.
- Attributes:
dataarray of uint8The parentheses bit array (1 = open, 0 = close).
Notes
The tree’s arrays, including the navigation index built from
data, are held by this Python object. Operations on them are computed by a compiled (Cython) engine: per-node navigation methods (e.g.,parent,lca) are bound directly to the engine when the tree is created, so they run at compiled speed.The navigation methods take positions in
data, from 0 todata.size - 1. For any other position, e.g. the -1 thatparentreturns for the root, they return -1 (is_tipandis_ancestorreturn False) rather than read outside the tree’s arrays, so a -1 passed from one method to another gives -1 again.A tree created from a non-NumPy
B, e.g. a CuPy array or a PyTorch tensor on a GPU, keepsBas itsdataand a host copy of it, from which it is built and navigated as any other tree. The node attributes (lengths,names,edges) are NumPy arrays on the host. A tree created otherwise, e.g. read from a file, is moved to a GPU (or any backend and device) withto_device, which rebuilds nothing.The batch operations (e.g.
lca_batch) andcophenetwithengine="numba"run on the GPU ifBis on a CUDA or ROCm device and a Numba GPU extension for it is installed (numba-cuda-mlir, or the deprecated numba-cuda, on CUDA; numba-hip on ROCm). Otherwise, or if the GPU kernel cannot be built on the system (which is warned about once), they run on the host. A call that runs out of device memory runs on the host, with a warning, and later calls still run on the GPU.On a GPU, they run on the device of
data, whichever device is current; queries on another GPU raise aValueError.The batch operations return their result in the array backend and on the device of their queries, and
copheneta distance matrix in those ofdata.Operations creating a new tree (
shear,collapse, pickling) and those exporting it (to_array,to_npz) work on the host copy, and create NumPy trees and arrays.
The
fastengine. The batch operations andcophenetrun the same algorithm, with bit-identical results, on either engine, soengine="fast"is chosen from where the tree is and how scikit-bio was built, rather than fixed:"numba"if the tree’sdatais on a GPU the Numba kernels can use (see above).Otherwise
"cython"if scikit-bio was built with OpenMP, as it is with GCC on Linux: its kernels are multithreaded, and compile nothing at the first call, where Numba compiles each kernel.Otherwise
"numba"if Numba is installed, as the Cython kernels then run on a single thread.Otherwise
"cython".
After a GPU kernel has failed on the system,
"fast"follows rules 2-4.References
[1] http://www.dcc.uchile.cl/~gnavarro/ps/tcs16.2.pdf
Attributes
The parentheses bit array (1 = open, 0 = close).
Edge number per parenthesis (read at opening parentheses).
Branch length per parenthesis (read at opening parentheses).
Tree IO
Create a new
BPTreeinstance from a file.Write an instance of
BPTreeto a file.Save the tree to a compressed NumPy
.npzarchive.Load a tree from a NumPy
.npzarchive written byto_npz.Tree navigation
The index of the root node of the tree.
The parent of node.
Index of the first (leftmost) child of a node.
Index of the last (rightmost) child of a node.
Index of the next (right) sibling of a node.
Index of the previous (left) sibling of a node.
The lowest common ancestor of two nodes.
Whether a node is an ancestor of another node.
Index of the deepest node descending from a node.
Tree traversal
Preorder rank of a node.
Postorder rank of a node.
Index of the node with a given preorder rank.
Index of the node with a given postorder rank.
Index of the ancestor a given number of levels above a node.
Index of the next node at the same depth.
Tree analysis
Whether the node is a tip of a tree.
The depth of given node.
The height of node i with respect to its deepest descendent
Get the count of nodes in the subtree rooted at a node.
Batch operations
Matching closing parenthesis of each position in a batch.
Parent of each node in a batch.
Lowest common ancestor of each pair of nodes in a batch.
Ancestor a given number of levels above each node in a batch.
Return a distance matrix between each pair of tips in the tree.
Node positions and compiled kernels
Positions of the tips, in tree order.
Positions of named nodes.
Name of a node.
The tree's arrays, for the Numba navigation functions.
Tree manipulation
Remove all nodes from the tree except tips and ancestors of tips.
Collapse single-child internal nodes.
Tree conversion
Construct a BPTree from a
TreeNode.Return an array representation of the tree.
Return this tree with its data in an array backend and on a device.
Special methods
Special methods (inherited)
__eq__Return self==value.
__ge__Return self>=value.
__getstate__Helper for pickle.
__gt__Return self>value.
__hash__Return hash(self).
__le__Return self<=value.
__lt__Return self<value.
__ne__Return self!=value.
Details
- data#
The parentheses bit array (1 = open, 0 = close).
It is in the array backend and on the device of the array the tree was created from. For a NumPy array, it is a read-only view: the topology cannot change once the tree exists, as the navigation index is built from it. The tree keeps the array it was created from, without a copy, so that array must not be changed either.
- default_write_format = 'newick'#
- edges#
Edge number per parenthesis (read at opening parentheses).
A read-only view: use
set_edgesto change the edge numbers. It is a NumPy array on the host, whatever the backend ofdata.