Skip to content

Commit f2a1189

Browse files
committed
v0.5.0 enhance documentation, tidy codes
1 parent d1322e0 commit f2a1189

24 files changed

+440
-133
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Work In Progress
99
- Node: WeightedNode for weighted edge tree implementation.
1010

11+
## [0.5.0] - 2022-11-09
12+
### Added
13+
- Clean codes and documentation.
14+
15+
### Changed
16+
- Tree Exporter: Printing tree to group multiple arguments together.
17+
- DAG and Tree Exporter: Export to dot able to plot multiple disjointed trees/dags, rename `bgcolor` to `bg_colour`
18+
1119
## [0.4.6] - 2022-11-09
1220
### Added
1321
- Tree Constructor: From DataFrame of parent-child columns.
@@ -84,6 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8492
- Utility Iterator: Tree traversal methods.
8593
- Workflow To Do App: Tree use case with to-do list implementation.
8694

95+
[0.5.0]: https://github.com/kayjan/bigtree/compare/v0.4.6...v0.5.0
8796
[0.4.6]: https://github.com/kayjan/bigtree/compare/v0.4.5...v0.4.6
8897
[0.4.5]: https://github.com/kayjan/bigtree/compare/v0.4.4...v0.4.5
8998
[0.4.4]: https://github.com/kayjan/bigtree/compare/v0.4.3...v0.4.4

README.md

+27-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@ Tree Implementation for Python, integrated with Python list, dictionary, and pan
44

55
It is pythonic, making it easy to learn and extendable to many types of workflows.
66

7+
----
8+
79
Related Links:
810
- [Documentation](https://bigtree.readthedocs.io/en/latest/)
911
- [GitHub](https://github.com/kayjan/bigtree/)
1012
- [Changelog](https://github.com/kayjan/bigtree/blob/master/CHANGELOG.md)
1113
- [PyPI](https://pypi.org/project/bigtree/)
14+
- Articles
15+
- [Python Tree Implementation with BigTree](https://towardsdatascience.com/python-tree-implementation-with-bigtree-13cdabd77adc#245a-94ae81f0b3f1)
16+
17+
----
1218

1319
## Components
1420
There are 2 segments to Big Tree consisting of Tree implementation and Directed Acyclic Graph (DAG) implementation.
@@ -70,15 +76,19 @@ For Directed Acyclic Graph (DAG) implementation, there are 4 main components.
7076

7177
To install `bigtree`, run the following line in command prompt:
7278

73-
```pip install bigtree```
79+
```shell
80+
$ pip install bigtree
81+
```
7482

7583
If tree needs to be exported to image, it requires additional dependencies.
7684
Run the following lines in command prompt:
7785

86+
```shell
87+
$ pip install 'bigtree[image]'
88+
$ brew install gprof2dot
7889
```
79-
pip install 'bigtree[image]'
80-
brew install gprof2dot
81-
```
90+
91+
----
8292

8393
## Tree Demonstration
8494

@@ -94,7 +104,7 @@ Nodes can be linked to each other with `parent` and `children` setter methods,
94104
or using bitshift operator with the convention `parent_node >> child_node` or `child_node << parent_node`.
95105

96106
```python
97-
from bigtree import Node, print_tree
107+
from bigtree import Node, print_tree, tree_to_dot
98108

99109
root = Node("a", age=90)
100110
b = Node("b", age=65)
@@ -109,8 +119,13 @@ print_tree(root, attr_list=["age"])
109119
# ├── b [age=65]
110120
# │ └── d [age=40]
111121
# └── c [age=60]
122+
123+
graph = tree_to_dot(root, node_colour="gold")
124+
graph.write_png("assets/tree.png")
112125
```
113126

127+
![Sample Tree Output](../../assets/tree.png)
128+
114129
```python
115130
from bigtree import Node, print_tree
116131

@@ -643,6 +658,8 @@ graph.write_png("assets/demo.png")
643658

644659
![Sample Tree Output](../../assets/demo.png)
645660

661+
----
662+
646663
## DAG Demonstration
647664

648665
Compared to nodes in tree, nodes in DAG are able to have multiple parents.
@@ -734,6 +751,8 @@ print([(parent.node_name, child.node_name) for parent, child in dag_iterator(dag
734751
# [('a', 'd'), ('c', 'd'), ('d', 'e'), ('a', 'c'), ('b', 'c')]
735752
```
736753

754+
----
755+
737756
## Demo Usage
738757

739758
### To Do Application
@@ -760,4 +779,7 @@ app.show()
760779
# │ └── Bread [description=Urgent]
761780
# └── General
762781
# └── Cook
782+
783+
app.save("list.json")
784+
app2 = AppToDo.load("list.json")
763785
```

assets/dag_construct.png

14 KB
Loading

assets/tree.png

9.97 KB
Loading

assets/tree_construct.png

63.1 KB
Loading

bigtree/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.4.6"
1+
__version__ = "0.5.0"
22

33
from bigtree.dag.construct import dataframe_to_dag, dict_to_dag, list_to_dag
44
from bigtree.dag.export import dag_to_dataframe, dag_to_dict, dag_to_dot, dag_to_list

bigtree/dag/construct.py

+4-18
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,10 @@ def list_to_dag(
2828
Returns:
2929
(DAGNode)
3030
"""
31-
node_dict = dict()
32-
parent_node = None
33-
34-
for parent_name, child_name in relations:
35-
parent_node = node_dict.get(parent_name)
36-
if not parent_node:
37-
parent_node = node_type(parent_name)
38-
39-
child_node = node_dict.get(child_name)
40-
if not child_node:
41-
child_node = node_type(child_name)
42-
43-
node_dict[parent_name] = parent_node
44-
node_dict[child_name] = child_node
45-
46-
parent_node.children = [child_node]
47-
48-
return parent_node
31+
relation_data = pd.DataFrame(relations, columns=["parent", "child"])
32+
return dataframe_to_dag(
33+
relation_data, child_col="child", parent_col="parent", node_type=node_type
34+
)
4935

5036

5137
def dict_to_dag(

bigtree/dag/export.py

+37-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, List, Tuple
1+
from typing import Any, Dict, List, Tuple, Union
22

33
import pandas as pd
44

@@ -161,14 +161,14 @@ def dag_to_dataframe(
161161

162162

163163
def dag_to_dot(
164-
dag: DAGNode,
164+
dag: Union[DAGNode, List[DAGNode]],
165165
rankdir: str = "TB",
166-
bgcolor: str = None,
166+
bg_colour: str = None,
167167
node_colour: str = None,
168168
edge_colour: str = None,
169169
node_attr: str = None,
170170
):
171-
r"""Export DAG tree to image.
171+
r"""Export DAG tree or list of DAG trees to image.
172172
Note that node names must be unique.
173173
Posible node attributes include style, fillcolor, shape.
174174
@@ -188,12 +188,12 @@ def dag_to_dot(
188188
Export to string
189189
190190
>>> dag_graph.to_string()
191-
'strict digraph G {\nrankdir=TB;\na [label=a];\nc [label=c];\na -> c;\na [label=a];\nd [label=d];\na -> d;\nb [label=b];\nc [label=c];\nb -> c;\nc [label=c];\nd [label=d];\nc -> d;\nd [label=d];\ne [label=e];\nd -> e;\n}\n'
191+
'strict digraph G {\nrankdir=TB;\nc [label=c];\na [label=a];\na -> c;\nd [label=d];\na [label=a];\na -> d;\nc [label=c];\nb [label=b];\nb -> c;\nd [label=d];\nc [label=c];\nc -> d;\ne [label=e];\nd [label=d];\nd -> e;\n}\n'
192192
193193
Args:
194194
dag (DAGNode): tree to be exported
195195
rankdir (str): set direction of graph layout, defaults to 'TB', can be 'BT, 'LR', 'RL'
196-
bgcolor (str): background color of image, defaults to None
196+
bg_colour (str): background color of image, defaults to None
197197
node_colour (str): fill colour of nodes, defaults to None
198198
edge_colour (str): colour of edges, defaults to None
199199
node_attr (str): node attribute for style, overrides node_colour, defaults to None
@@ -208,12 +208,9 @@ def dag_to_dot(
208208
"pydot not available. Please perform a\n\npip install 'bigtree[image]'\n\nto install required dependencies"
209209
)
210210

211-
if not isinstance(dag, DAGNode):
212-
raise ValueError("Tree should be of type `DAGNode`, or inherit from `DAGNode`")
213-
214211
# Get style
215-
if bgcolor:
216-
graph_style = dict(bgcolor=bgcolor)
212+
if bg_colour:
213+
graph_style = dict(bgcolor=bg_colour)
217214
else:
218215
graph_style = dict()
219216

@@ -227,30 +224,40 @@ def dag_to_dot(
227224
else:
228225
edge_style = dict()
229226

230-
dag = dag.copy()
231-
232227
_graph = pydot.Dot(
233228
graph_type="digraph", strict=True, rankdir=rankdir, **graph_style
234229
)
235230

236-
for parent_node, child_node in dag_iterator(dag):
237-
parent_name = parent_node.name
238-
parent_node_style = node_style.copy()
239-
if node_attr and parent_node.get_attr(node_attr):
240-
parent_node_style.update(parent_node.get_attr(node_attr))
241-
pydot_parent = pydot.Node(
242-
name=parent_name, label=parent_name, **parent_node_style
243-
)
244-
_graph.add_node(pydot_parent)
231+
if not isinstance(dag, list):
232+
dag = [dag]
245233

246-
child_name = child_node.name
247-
child_node_style = node_style.copy()
248-
if node_attr and child_node.get_attr(node_attr):
249-
child_node_style.update(child_node.get_attr(node_attr))
250-
pydot_child = pydot.Node(name=child_name, label=child_name, **parent_node_style)
251-
_graph.add_node(pydot_child)
234+
for _dag in dag:
235+
if not isinstance(_dag, DAGNode):
236+
raise ValueError(
237+
"Tree should be of type `DAGNode`, or inherit from `DAGNode`"
238+
)
239+
_dag = _dag.copy()
240+
241+
for parent_node, child_node in dag_iterator(_dag):
242+
child_name = child_node.name
243+
child_node_style = node_style.copy()
244+
if node_attr and child_node.get_attr(node_attr):
245+
child_node_style.update(child_node.get_attr(node_attr))
246+
pydot_child = pydot.Node(
247+
name=child_name, label=child_name, **child_node_style
248+
)
249+
_graph.add_node(pydot_child)
250+
251+
parent_name = parent_node.name
252+
parent_node_style = node_style.copy()
253+
if node_attr and parent_node.get_attr(node_attr):
254+
parent_node_style.update(parent_node.get_attr(node_attr))
255+
pydot_parent = pydot.Node(
256+
name=parent_name, label=parent_name, **parent_node_style
257+
)
258+
_graph.add_node(pydot_parent)
252259

253-
edge = pydot.Edge(parent_name, child_name, **edge_style)
254-
_graph.add_edge(edge)
260+
edge = pydot.Edge(parent_name, child_name, **edge_style)
261+
_graph.add_edge(edge)
255262

256263
return _graph

bigtree/node/basenode.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class BaseNode:
106106
3. ``set_attrs(attrs: dict)``: Set node attribute name(s) and value(s)
107107
4. ``copy()``: Deep copy BaseNode
108108
109-
------------
109+
----
110110
111111
"""
112112

bigtree/node/dagnode.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class DAGNode:
9292
3. ``set_attrs(attrs: dict)``: Set node attribute name(s) and value(s)
9393
4. ``copy()``: Deep copy DAGNode
9494
95-
------------
95+
----
9696
9797
"""
9898

bigtree/node/node.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class Node(BaseNode):
5757
1. ``node_name``: Get node name, without accessing `name` directly
5858
2. ``path_name``: Get path name from root, separated by `sep`
5959
60-
------------
60+
----
6161
6262
"""
6363

0 commit comments

Comments
 (0)