Skip to content
/ anytree Public

Rudimentary model of electrical grid's causal structure for playing with, built on @c0fec0de's excellent tree library

License

Notifications You must be signed in to change notification settings

nline/anytree

Repository files navigation

https://img.shields.io/pypi/dm/anytree.svg?label=pypi%20downloads https://travis-ci.org/c0fec0de/anytree.svg?branch=master https://readthedocs.org/projects/anytree/badge/?version=2.8.0 https://codeclimate.com/github/c0fec0de/anytree.png

Links

https://github.com/c0fec0de/anytree/raw/devel/docs/static/buymeacoffee.png

Getting started

Usage is simple.

Construction

>>> from anytree import Node, RenderTree
>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> dan = Node("Dan", parent=udo)
>>> jet = Node("Jet", parent=dan)
>>> jan = Node("Jan", parent=dan)
>>> joe = Node("Joe", parent=dan)

Node

>>> print(udo)
Node('/Udo')
>>> print(joe)
Node('/Udo/Dan/Joe')

Tree

>>> for pre, fill, node in RenderTree(udo):
...     print("%s%s" % (pre, node.name))
Udo
├── Marc
│   └── Lian
└── Dan
    ├── Jet
    ├── Jan
    └── Joe

For details see Node and RenderTree.

nLine

Create tree model of the electrical grid. Each node has a failrate. When you refresh the tree, if a parent fails, the failure propagates to all the children and the children's children, etc. Very primitive for now! More functionality coming. Update: failrate defaults to zero and you an set a node's status. When you use setstatus the sub-tree is refreshed.

>>> from anytree import Node, RenderTree
>>> prim = Node("Prim", failrate=50)
>>> seco = Node("Seco", failrate=20)
>>> seco = Node("Seco", failrate=20, parent=prim)
>>> sensor = Node("Sensor", failrate=0, parent=seco)
>>> tinytim = Node("Tiny Tim", failrate=0, parent=seco)
>>> seco2 = Node("Seco2", failrate=90, parent=prim)
>>> giulio = Node("Giulio", failrate=0, parent=seco2)
>>> for pre, fill, node in RenderTree(prim):
...     print("%s%s %s" % (pre, node.status, node.name))
...
1 Prim
├── 1 Seco
│   ├── 1 Sensor
│   └── 1 Tiny Tim
└── 1 Seco2
    └── 1 Giulio
>>> seco.setstatus(0)
>>> for pre, fill, node in RenderTree(prim):
...     print("%s%s %s" % (pre, node.status, node.name))
...
1 Prim
├── 0 Seco
│   ├── 0 Sensor
│   └── 0 Tiny Tim
└── 1 Seco2
    └── 1 Giulio

Visualization

>>> from anytree.exporter import DotExporter
>>> # graphviz needs to be installed for the next line!
>>> DotExporter(udo).to_picture("udo.png")

https://anytree.readthedocs.io/en/latest/_images/udo.png

The DotExporter can be started at any node and has various formatting hookups:

>>> DotExporter(dan,
...             nodeattrfunc=lambda node: "fixedsize=true, width=1, height=1, shape=diamond",
...             edgeattrfunc=lambda parent, child: "style=bold"
... ).to_picture("dan.png")

https://anytree.readthedocs.io/en/latest/_images/dan.png

There are various other Importers and Exporters.

Manipulation

A second tree:

>>> mary = Node("Mary")
>>> urs = Node("Urs", parent=mary)
>>> chris = Node("Chris", parent=mary)
>>> marta = Node("Marta", parent=mary)
>>> print(RenderTree(mary))
Node('/Mary')
├── Node('/Mary/Urs')
├── Node('/Mary/Chris')
└── Node('/Mary/Marta')

Append:

>>> udo.parent = mary
>>> print(RenderTree(mary))
Node('/Mary')
├── Node('/Mary/Urs')
├── Node('/Mary/Chris')
├── Node('/Mary/Marta')
└── Node('/Mary/Udo')
    ├── Node('/Mary/Udo/Marc')
    │   └── Node('/Mary/Udo/Marc/Lian')
    └── Node('/Mary/Udo/Dan')
        ├── Node('/Mary/Udo/Dan/Jet')
        ├── Node('/Mary/Udo/Dan/Jan')
        └── Node('/Mary/Udo/Dan/Joe')

Subtree rendering:

>>> print(RenderTree(marc))
Node('/Mary/Udo/Marc')
└── Node('/Mary/Udo/Marc/Lian')

Cut:

>>> dan.parent = None
>>> print(RenderTree(dan))
Node('/Dan')
├── Node('/Dan/Jet')
├── Node('/Dan/Jan')
└── Node('/Dan/Joe')

Extending any python class to become a tree node

The enitre tree magic is encapsulated by NodeMixin add it as base class and the class becomes a tree node:

>>> from anytree import NodeMixin, RenderTree
>>> class MyBaseClass(object):  # Just an example of a base class
...     foo = 4
>>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
...     def __init__(self, name, length, width, parent=None, children=None):
...         super(MyClass, self).__init__()
...         self.name = name
...         self.length = length
...         self.width = width
...         self.parent = parent
...         if children:
...             self.children = children

Just set the parent attribute to reflect the tree relation:

>>> my0 = MyClass('my0', 0, 0)
>>> my1 = MyClass('my1', 1, 0, parent=my0)
>>> my2 = MyClass('my2', 0, 2, parent=my0)
>>> for pre, fill, node in RenderTree(my0):
...     treestr = u"%s%s" % (pre, node.name)
...     print(treestr.ljust(8), node.length, node.width)
my0      0 0
├── my1  1 0
└── my2  0 2

The children can be used likewise:

>>> my0 = MyClass('my0', 0, 0, children=[
...     MyClass('my1', 1, 0),
...     MyClass('my2', 0, 2),
... ])
>>> for pre, fill, node in RenderTree(my0):
...     treestr = u"%s%s" % (pre, node.name)
...     print(treestr.ljust(8), node.length, node.width)
my0      0 0
├── my1  1 0
└── my2  0 2

Documentation

Please see the Documentation for all details.

Installation

To install the anytree module run:

pip install anytree

If you do not have write-permissions to the python installation, try:

pip install anytree --user

About

Rudimentary model of electrical grid's causal structure for playing with, built on @c0fec0de's excellent tree library

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages