Skip to content
Merged
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- BaseNode: Method `get_common_ancestors` for getting common ancestors, this was already available in parsing module.
- Docs: Enumerate the demonstration page, fix url links.
- Docs: Update demonstration to include query examples.

## [1.4.1] - 2026-05-02
### Changed:
- Tree Helper: Tree diff modify type hint to include returning None.
- Tree Diff: Modify type hint to include returning None.
- Misc: Mypy type checks to remove ignoring warn_no_return.

## [1.4.1] - 2026-05-02
Expand Down
5 changes: 4 additions & 1 deletion bigtree/_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def register_binarytree_plugins() -> None:
# Iterator methods
"inorder_iter": iterators.inorder_iter,
},
method="default",
)

plugin_docs = "\n".join(
Expand Down Expand Up @@ -52,6 +53,7 @@ def register_dag_plugins() -> None:
# Iterator methods
"iterate": iterators.dag_iterator,
},
method="default",
)

plugin_docs = "\n".join(
Expand Down Expand Up @@ -143,7 +145,8 @@ def register_tree_plugins() -> None:
"find_children": search.find_children,
"find_child": search.find_child,
"find_child_by_name": search.find_child_by_name,
}
},
method="default",
)
Tree.register_plugins(
{
Expand Down
27 changes: 19 additions & 8 deletions bigtree/node/basenode.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ class BaseNode:
1. ``describe()``: Get node information sorted by attributes, return list of tuples
2. ``get_attr(attr_name: str)``: Get value of node attribute
3. ``set_attrs(attrs: dict)``: Set node attribute name(s) and value(s)
4. ``go_to(node: Self)``: Get a path from own node to another node from same tree
5. ``append(node: Self)``: Add child to node
6. ``extend(nodes: list[Self])``: Add multiple children to node
7. ``copy()``: Deep copy self
8. ``sort()``: Sort child nodes
9. ``plot()``: Plot tree in line form
10. ``query(query: str)``: Filter tree using Tree Query Language
4. ``get_common_ancestors(node: Self)``: Get common ancestors with another node from same tree
5. ``go_to(node: Self)``: Get a path from own node to another node from same tree
6. ``append(node: Self)``: Add child to node
7. ``extend(nodes: list[Self])``: Add multiple children to node
8. ``copy()``: Deep copy self
9. ``sort()``: Sort child nodes
10. ``plot()``: Plot tree in line form
11. ``query(query: str)``: Filter tree using Tree Query Language

----

Expand Down Expand Up @@ -652,8 +653,18 @@ def set_attrs(self, attrs: Mapping[str, Any]) -> None:
"""
self.__dict__.update(attrs)

def get_common_ancestors(self: T, node: T) -> Iterable[T]:
"""Get common ancestors of current node and specified node from same tree.

Args:
node: node to get common ancestors
"""
from bigtree.tree.parsing import get_common_ancestors

return get_common_ancestors([self, node])

def go_to(self: T, node: T) -> Iterable[T]:
"""Get path from current node to specified node from same tree, uses `get_path` function.
"""Get path from current node to specified node from same tree.

Args:
node: node to travel to from current node, inclusive of start and end node
Expand Down
8 changes: 4 additions & 4 deletions docs/gettingstarted/demo/binarytree.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Compared to nodes in tree, nodes in Binary Tree are only allowed maximum of 2 ch
Since BinaryNode extends from Node, construct, traverse, search, export methods from Node are applicable to
Binary Tree as well.

## Construct Binary Tree
## 1. Construct Binary Tree

### 1. From BinaryNode
### 1.1 From BinaryNode

BinaryNode can be linked to each other with `parent`, `children`, `left`, and `right` setter methods,
or using bitshift operator with the convention `parent_node >> child_node` or `child_node << parent_node`.
Expand All @@ -37,7 +37,7 @@ graph.write_png("assets/demo/binarytree.png")

![Sample Binary Tree Output](https://github.com/kayjan/bigtree/raw/master/assets/demo/binarytree.png "Sample Binary Tree Output")

### 2. From list
### 1.2 From list

Construct nodes only, list has similar format as `heapq` list.

Expand All @@ -56,7 +56,7 @@ tree.hshow()
# └─ 7
```

## Traverse Binary Tree
## 2. Traverse Binary Tree

In addition to the traversal methods in the usual tree, binary tree includes in-order traversal method.

Expand Down
12 changes: 6 additions & 6 deletions docs/gettingstarted/demo/dag.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ to implement dag-level methods (for construct/export etc.) for a more intuitive

Compared to nodes in tree, nodes in DAG are able to have multiple parents.

## Construct DAG
## 1. Construct DAG

### 1. From DAGNode
### 1.1 From DAGNode

DAGNodes can be linked to each other in the following ways:

Expand All @@ -39,7 +39,7 @@ graph.write_png("assets/demo/dag.png")

![Sample DAG Output](https://github.com/kayjan/bigtree/raw/master/assets/demo/dag.png "Sample DAG Output")

### 2. From list
### 1.2 From list

Construct nodes only, list contains parent-child tuples.

Expand All @@ -53,7 +53,7 @@ print([(parent.node_name, child.node_name) for parent, child in dag.iterate()])
# [('a', 'd'), ('c', 'd'), ('d', 'e'), ('a', 'c'), ('b', 'c')]
```

### 3. From nested dictionary
### 1.3 From nested dictionary

Construct nodes with attributes, `key`: child name, `value`: dict of parent name, child node attributes.

Expand All @@ -73,7 +73,7 @@ print([(parent.node_name, child.node_name) for parent, child in dag.iterate()])
# [('a', 'd'), ('c', 'd'), ('d', 'e'), ('a', 'c'), ('b', 'c')]
```

### 4. From pandas DataFrame
### 1.4 From pandas DataFrame

Construct nodes with attributes, *pandas DataFrame* contains child column, parent column, and attribute columns.

Expand All @@ -99,7 +99,7 @@ print([(parent.node_name, child.node_name) for parent, child in dag.iterate()])
# [('a', 'd'), ('c', 'd'), ('d', 'e'), ('a', 'c'), ('b', 'c')]
```

## DAG Attributes and Operations
## 2. DAG Attributes and Operations

Note that using `DAGNode` as superclass inherits the default class attributes (properties) and operations (methods).

Expand Down
76 changes: 50 additions & 26 deletions docs/gettingstarted/demo/tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ implement tree-level methods for a more intuitive API.

Here are some codes to get started.

## Construct Tree
## 1. Construct Tree

Nodes can have attributes if they are initialized from `Node`, *dictionary*, *pandas DataFrame*, or *polars DataFrame*.
Read more [here](/../../bigtree/tree/tree/#tree-construct-methods).
Read more [here](https://bigtree.readthedocs.io/stable/bigtree/tree/construct/#tree-construct-methods).

### 1. From Node
### 1.1 From Node

Nodes can be linked to each other in the following ways:

Expand Down Expand Up @@ -104,7 +104,7 @@ Nodes can be linked to each other in the following ways:

![Sample Tree Output](https://github.com/kayjan/bigtree/raw/master/assets/demo/tree.png "Sample Tree Output")

### 2. From str
### 1.2 From str

Construct nodes only. Newick string notation supports parsing attributes.

Expand Down Expand Up @@ -153,7 +153,7 @@ Construct nodes only. Newick string notation supports parsing attributes.
# └── f
```

### 3. From list
### 1.3 From list

Construct nodes only. List can contain either <mark>full paths</mark> or tuples of <mark>parent-child names</mark>.

Expand Down Expand Up @@ -183,7 +183,7 @@ Construct nodes only. List can contain either <mark>full paths</mark> or tuples
# └── c
```

### 4. From nested dictionary
### 1.4 From nested dictionary

Construct nodes with attributes. Dictionary can be in a <mark>flat structure</mark> where `key` is path and `value` is
dictionary of node attribute names and values, or in a <mark>recursive structure</mark> where `key` is node attribute
Expand Down Expand Up @@ -277,7 +277,7 @@ names and `value` is node attribute values, and list of children (recursive).
```


### 5. From pandas/polars DataFrame
### 1.5 From pandas/polars DataFrame

Construct nodes with attributes. *DataFrame* can contain either <mark>path column</mark> or
<mark>parent-child columns</mark>. Other columns can be used to specify attributes.
Expand Down Expand Up @@ -378,7 +378,7 @@ Construct nodes with attributes. *DataFrame* can contain either <mark>path colum
# └── c [age=60]
```

### 6. From rich Trees
### 1.6 From rich Trees

Convert rich.tree.Tree to bigtree Trees.

Expand Down Expand Up @@ -408,9 +408,9 @@ Convert rich.tree.Tree to bigtree Trees.
If tree is already created, nodes can still be added using path string, dictionary, and pandas/polars DataFrame!<br>
Attributes can be added to existing nodes using a dictionary or pandas/polars DataFrame.

## View Tree
## 2. View Tree

### 1. Print Tree
### 2.1 Print Tree

After tree is constructed, it can be viewed by printing to console using `show`, `hshow`, or `vshow` method directly,
for compact, horizontal, and vertical orientation respectively.
Expand Down Expand Up @@ -578,7 +578,7 @@ Other customisations for printing are also available, such as:
# └── c
```

### 2. Display on Jupyter Notebook
### 2.2 Display in Jupyter Notebook

Tree can be displayed interactively on jupyter notebook using `ishow`.

Expand Down Expand Up @@ -606,7 +606,7 @@ tree.ishow(all_attrs=True, height=400) # (1)!
</div>


### 3. Plot Tree
### 2.3 Plot Tree

Tree can also be plotted using `plot` method directly with the help of `matplotlib` library.

Expand Down Expand Up @@ -635,7 +635,7 @@ fig.savefig("assets/demo/tree_plot.png") # Save figure

![Tree Plot Image Output](https://github.com/kayjan/bigtree/raw/master/assets/demo/tree_plot.png "Tree Plot Image Output")

## Tree Attributes and Operations
## 3. Tree Attributes and Operations

Note that using `BaseNode` or `Node` as superclass inherits the default class attributes (properties)
and operations (methods).
Expand Down Expand Up @@ -693,7 +693,8 @@ Below is the table of operations available to `BaseNode` and `Node` classes.
|------------------------------------|------------------------------------------------------------------|--------------------------------------------|
| Visualize tree (only for `Node`) | `root.show()` / `root.hshow()` / `root.vshow()` | None |
| Get node information | `root.describe(exclude_prefix="_")` | [('name', 'a')] |
| Find path from one node to another | `root.go_to(node_e)` | [Node(/a, ), Node(/a/b, ), Node(/a/b/e, )] |
| Find common ancestors | `root.get_common_ancestors(node_e)` | [Node(/a/b, ), Node(/a/b/e, )] |
| Find path from one node to another | `node_b.go_to(node_e)` | [Node(/a, ), Node(/a/b, ), Node(/a/b/e, )] |
| Add one or more children to node | `root.append(Node("j"))` / `root.extend([Node("k"), Node("l")])` | Node(/a, ) |
| Set attribute(s) | `root.set_attrs({"description": "root-tag"})` | None |
| Get attribute | `root.get_attr("description")` | 'root-tag' |
Expand All @@ -702,7 +703,7 @@ Below is the table of operations available to `BaseNode` and `Node` classes.
| Plot tree | `root.plot("-ok")` | plt.Figure() |
| Query tree | `root.query('name == "b"')` | [Node(/a/b, )] |

## Traverse Tree
## 4. Traverse Tree

Tree can be traversed using the following traversal methods.

Expand Down Expand Up @@ -742,7 +743,7 @@ a
# [['a'], ['c', 'b'], ['d', 'e']]
```

## Modify Tree
## 5. Modify Tree

Nodes can be <mark>shifted</mark> (with or without replacement) or <mark>copied</mark> (without replacement)
from one path to another, this changes the tree in-place.
Expand Down Expand Up @@ -887,13 +888,15 @@ root_other.show()
4. The first copy and replace of `Documents/Pictures/photo2.jpg` with `photo1.jpg`
5. The second copy and replace of `Documents/file2.doc` with `file1.doc`

## Tree Search
## 6. Tree Search and Query

One or multiple nodes can be searched based on name, path, attribute value, or user-defined condition.
It is also possible to search for one or more child node(s) based on attributes, this search will be faster as
it does not require traversing the whole tree to find the node(s).

Read more [here](/../../bigtree/tree/tree/#tree-query-and-search-methods).
Tree can be queried using Tree Query Language.

Read more [here](https://bigtree.readthedocs.io/stable/bigtree/tree/tree/#tree-query-and-search-methods).

=== "Find single node"
```python hl_lines="13 16 19 22 25 28"
Expand Down Expand Up @@ -985,11 +988,32 @@ Read more [here](/../../bigtree/tree/tree/#tree-query-and-search-methods).
# Node(/a/c/c, age=40)
```

## Helper Utility
=== "Tree Query"
```python hl_lines="13 16"
from bigtree import Node, Tree
root = Node("a", age=90)
b = Node("b", age=65, parent=root)
c = Node("c", age=60, parent=root)
d = Node("d", age=40, parent=c)
tree = Tree(root)
tree.show(attr_list=["age"])
# a [age=90]
# ├── b [age=65]
# └── c [age=60]
# └── d [age=40]

tree.query('name == "b" OR age <= 40')
# [Node(/a/b, age=65), Node(/a/c/d, age=40)]

tree.query("is_leaf")
# [Node(/a/b, age=65), Node(/a/c/d, age=40)]
```

## 7. Helper Utility

Read more [here](/../../bigtree/tree/tree/#tree-helper-methods).
Read more [here](https://bigtree.readthedocs.io/stable/bigtree/tree/tree/#tree-helper-methods).

### 1. Clone tree
### 7.1 Clone tree

Trees can be cloned to another Node type. If the same type is desired, use `tree.copy()` instead.

Expand All @@ -1003,7 +1027,7 @@ clone_tree(root, Node) # clone from `BaseNode` to `Node` type
# Node(/a, )
```

### 2. Get subtree
### 7.2 Get subtree

Subtree refers to a smaller tree with a different tree root.

Expand All @@ -1026,7 +1050,7 @@ root_subtree.show()
# └── e
```

### 3. Prune tree
### 7.3 Prune tree

Pruned tree refers to a smaller tree with the same tree root. Trees can be pruned by one or more of the following filters:

Expand Down Expand Up @@ -1090,7 +1114,7 @@ Pruned tree refers to a smaller tree with the same tree root. Trees can be prune
# └── c
```

### 4. Get tree differences
### 7.4 Get tree differences

View the differences in structure and/or attributes between two trees. The changes reflected are relative to the first
tree. By default, only the differences are shown. It is possible to view the full original tree with the differences.
Expand Down Expand Up @@ -1282,7 +1306,7 @@ For aggregating the differences at the parent-level instead of having `(+)` and
# └── d (~) [tags=('original d', 'new d')]
```

## Export Tree
## 8. Export Tree

Tree can be exported to other data types:

Expand All @@ -1295,7 +1319,7 @@ Tree can be exported to other data types:
7. Mermaid Flowchart (can display on .md)
8. Pyvis Network (can display interactive .html)

Read more [here](/../../bigtree/tree/tree/#tree-export-methods).
Read more [here](https://bigtree.readthedocs.io/stable/bigtree/tree/tree/#tree-export-methods).

```python
from bigtree import Node, Tree
Expand Down
Loading
Loading