Skip to content

Commit

Permalink
v0.3.1 - add rankdir to dot export
Browse files Browse the repository at this point in the history
  • Loading branch information
kayjan committed Nov 7, 2022
1 parent 4ce55aa commit 1729d0c
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 14 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ All notable changes to this project will be documented in this file.
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]
## Unreleased
### Work In Progress
- Node: WeightedNode for weighted edge tree implementation.

## [0.3.1] - 2022-11-07
### Added
- Tree Exporter and DAG Exporter: More customizations for Node to dot and DAGNode to dot.

## [0.3.0] - 2022-11-05
### Added
- DAG Constructors: From list, nested dictionary, pandas DataFrame.
Expand All @@ -31,7 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Utility Iterators: Tree traversal methods.
- Workflow To Do App: Tree use case with to-do list implementation.

[Unreleased]: https://github.com/kayjan/bigtree/compare/HEAD...v0.2.0
[0.3.1]: https://github.com/kayjan/bigtree/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/kayjan/bigtree/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/kayjan/bigtree/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/kayjan/bigtree/releases/tag/v0.1.0
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,8 @@ tree_to_dataframe(
# 3 /a/b/e e b 35
# 4 /a/c c a 60

graph = tree_to_dot(root, node_colour="gold")
graph.write_png("demo.png")
graph = tree_to_dot(root, rankdir="BT", node_colour="gold")
graph.write_png("assets/demo.png")
```

![Sample Tree Output](../../assets/demo.png)
Expand Down
Binary file modified assets/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion bigtree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.3.0"
__version__ = "0.3.1"

from bigtree.dag.construct import dataframe_to_dag, dict_to_dag, list_to_dag
from bigtree.dag.export import dag_to_dot
Expand Down
6 changes: 5 additions & 1 deletion bigtree/dag/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

def dag_to_dot(
dag: DAGNode,
rankdir: str = "TB",
bgcolor: str = None,
node_colour: str = None,
edge_colour: str = None,
Expand Down Expand Up @@ -35,6 +36,7 @@ def dag_to_dot(
Args:
dag (DAGNode): tree to be exported
rankdir (str): set direction of graph layout, defaults to 'TB', can be 'BT, 'LR', 'RL'
bgcolor (str): background color of image, defaults to None
node_colour (str): fill colour of nodes, defaults to None
edge_colour (str): colour of edges, defaults to None
Expand Down Expand Up @@ -71,7 +73,9 @@ def dag_to_dot(

dag = dag.copy()

_graph = pydot.Dot(graph_type="digraph", strict=True, **graph_style)
_graph = pydot.Dot(
graph_type="digraph", strict=True, rankdir=rankdir, **graph_style
)

for parent_node, child_node in dag_iterator(dag):
parent_name = parent_node.name
Expand Down
10 changes: 8 additions & 2 deletions bigtree/tree/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ def recursive_append(node, parent_dict):
def tree_to_dot(
tree: Node,
directed: bool = True,
rankdir: str = "TB",
bgcolor: str = None,
node_colour: str = None,
edge_colour: str = None,
Expand Down Expand Up @@ -598,6 +599,7 @@ def tree_to_dot(
Args:
tree (Node): tree to be exported
directed (bool): indicator whether graph should be directed or undirected, defaults to True
rankdir (str): set direction of graph layout, defaults to 'TB', can be 'BT, 'LR', 'RL'
bgcolor (str): background color of image, defaults to None
node_colour (str): fill colour of nodes, defaults to None
edge_colour (str): colour of edges, defaults to None
Expand Down Expand Up @@ -635,9 +637,13 @@ def tree_to_dot(
tree = tree.copy()

if directed:
_graph = pydot.Dot(graph_type="digraph", strict=True, **graph_style)
_graph = pydot.Dot(
graph_type="digraph", strict=True, rankdir=rankdir, **graph_style
)
else:
_graph = pydot.Dot(graph_type="graph", strict=True, **graph_style)
_graph = pydot.Dot(
graph_type="graph", strict=True, rankdir=rankdir, **graph_style
)

def recursive_create_node_and_edges(parent_name, child_node):
child_name = child_node.node_name
Expand Down
30 changes: 24 additions & 6 deletions tests/tree/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,10 @@ def test_tree_to_dot(tree_node):
expected = """strict digraph G {\na [label=a];\nb [label=b];\nb -> a;\nd [label=d];\nd -> b;\ne [label=e];\ne -> b;\ng [label=g];\ng -> e;\nh [label=h];\nh -> e;\nc [label=c];\nc -> a;\nf [label=f];\nf -> c;\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

@staticmethod
def test_tree_to_dot_type_error(dag_node):
Expand All @@ -709,36 +712,51 @@ def test_tree_to_dot_directed(tree_node):
expected = """strict graph G {\na [label=a];\nb [label=b];\nb -- a;\nd [label=d];\nd -- b;\ne [label=e];\ne -- b;\ng [label=g];\ng -- e;\nh [label=h];\nh -- e;\nc [label=c];\nc -- a;\nf [label=f];\nf -- c;\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree_undirected.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

@staticmethod
def test_tree_to_dot_bg_color(tree_node):
graph = tree_to_dot(tree_node, bgcolor="blue")
expected = """strict digraph G {\nbgcolor=blue;\na [label=a];\nb [label=b];\nb -> a;\nd [label=d];\nd -> b;\ne [label=e];\ne -> b;\ng [label=g];\ng -> e;\nh [label=h];\nh -> e;\nc [label=c];\nc -> a;\nf [label=f];\nf -> c;\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree_bg.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

@staticmethod
def test_tree_to_dot_fill_color(tree_node):
graph = tree_to_dot(tree_node, node_colour="gold")
expected = """strict digraph G {\na [fillcolor=gold, label=a, style=filled];\nb [fillcolor=gold, label=b, style=filled];\nb -> a;\nd [fillcolor=gold, label=d, style=filled];\nd -> b;\ne [fillcolor=gold, label=e, style=filled];\ne -> b;\ng [fillcolor=gold, label=g, style=filled];\ng -> e;\nh [fillcolor=gold, label=h, style=filled];\nh -> e;\nc [fillcolor=gold, label=c, style=filled];\nc -> a;\nf [fillcolor=gold, label=f, style=filled];\nf -> c;\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree_fill.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

@staticmethod
def test_tree_to_dot_edge_colour(tree_node):
graph = tree_to_dot(tree_node, edge_colour="red")
expected = """strict digraph G {\na [label=a];\nb [label=b];\nb -> a [color=red];\nd [label=d];\nd -> b [color=red];\ne [label=e];\ne -> b [color=red];\ng [label=g];\ng -> e [color=red];\nh [label=h];\nh -> e [color=red];\nc [label=c];\nc -> a [color=red];\nf [label=f];\nf -> c [color=red];\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree_edge.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

@staticmethod
def test_tree_to_dot_node_attr(tree_node_style):
graph = tree_to_dot(tree_node_style, node_attr="node_style")
expected = """strict digraph G {\na [fillcolor=gold, label=a, style=filled];\nb [fillcolor=blue, label=b, style=filled];\nb -> a;\nd [fillcolor=green, label=d, style=filled];\nd -> b;\ng [fillcolor=red, label=g, style=filled];\ng -> d;\ne [fillcolor=green, label=e, style=filled];\ne -> b;\nh [fillcolor=red, label=h, style=filled];\nh -> e;\nc [fillcolor=blue, label=c, style=filled];\nc -> a;\nf [fillcolor=green, label=f, style=filled];\nf -> c;\n}\n"""
actual = graph.to_string()
graph.write_png("tests/tree_style.png")
assert expected == actual, "Graph string is wrong"
for expected_str in expected.split():
assert (
expected_str in actual
), f"Expected {expected_str} not in actual string"

0 comments on commit 1729d0c

Please sign in to comment.