How to use Session map¶
Bliss builds a graph of instances created in the session.
This is in fact a dynamic map where every instance is a node related to other nodes. Thanks to this map we can access instances at realtime, collect information and interact.
Let’s go further with some code.
Basic Map¶
BLISS [1]: from bliss import global_map
BLISS [2]: m = global_map # the map
BLISS [3]: len(m)
Out [3]: 5
BLISS [4]: list(m) # list of node ids
Out [4]: ['session', 'controllers', 'comms', 'counters','axes']
BLISS [5]: m['session'] # accessing an element
Out [5]: {'instance': 'session', 'tag': 'session', '_logger': <Logger session (WARNING)>}
BLISS [6]: m.G # the DiGrap low-level container
Out [6]: <networkx.classes.digraph.DiGraph object at 0x7fdc4fa435c0>
BLISS [7]: m.G.nodes # listing directly DiGraph nodes
Out [7]: NodeView(('session', 'controllers', 'comms', 'counters','axes'))
BLISS [8]: m.draw()
graph TD
global --> controllers
global --> comms
global --> counters
global --> axes
We can see that map.G
is an instance of DiGraph from networkx module and that has a length of 5.
We can also list the names of basic nodes of a session.
More complex map¶
BLISS [3]: from bliss import global_map
BLISS [4]: m = global_map # the map instance
BLISS [5]: roby = config.get('roby')
BLISS [6]: len(m)
Out [6]: 7
BLISS [7]: list(m)
Out [7]: ['session', 'controllers', 'comms', 'counters', 'axes', 140483187066584, 140483253486984]
BLISS [9]: m.draw()
graph TD
global --> controllers
global --> comms
global --> counters
global --> axes
controllers --> mockup
mockup --> roby
axes --> roby
After getting roby
the map increases the size to 7. In fact, also the controller mockup
was initialized.
Node IDs¶
Nodes can be identified by:
- Strings, identified by the string itself
- Other Instances, identified by python id(instance) number
Registering nodes¶
In the following code we will register two nodes: the first is a string
node, the second is an instance of a just defined class A.
You can notice some facts:
- The first argument is the instance that you want to register
- If it is a string the string itself (e.g. ‘my_node’)
- If it is an instance give it as a reference (e.g. myinst in the case above or self inside a class)
- If no parent is given the instance will be registered under “controllers”
- Going through
session.map.G[node_instance]
you can retrieve node information like weakref, logger and others.
BLISS [1]: from bliss import global_map
BLISS [2]: m = global_map
BLISS [3]: m.register('my_node')
BLISS [4]: class A():
...: pass
BLISS [5]: myinst = A()
BLISS [6]: m.register(myinst, parents_list=['my_node','counters'])
BLISS [7]: m.draw()
graph TD
global --> controllers
global --> comms
global --> counters
global --> axes
controllers --> my_node
my_node --> 140415995035040
counters --> 140415995035040
Conceptually we registered the instance a
of the class A
as a child of my_node and counters. If we were asked for what is it, we could suppose that is a counter for my_node. Just an example anyway.
For more examples on how to register a device, see: Logging a controller
Map Advanced features¶
The map is in fact a picture picture
of the runtime state of the session.
Through the map we can:
- visualize the map of existing instances
- get instance references and, with this, access every method/attribute
- introspect attributes
Visualize the map¶
As simple as:
from bliss import global_map
global_map.draw()
If you want to visualize only one part you can give a node as an argument and you will be given a partial view of the map.
roby = config.get('roby')
m = session.map
m.draw(roby)