netgraph
netgraph copied to clipboard
Support for joining edges with bounding boxes of text labels of nodes
netgraph
doesn't support enclosing text labels in nodes and directing edges to the bounding boxes of text labels. At the current version nodes could be regular polygons or circles only. BaseGraph.draw_edges
method instantiates edge_artist
that supports offset that is constant:
edge_artist = EdgeArtist(
...
offset = node_size[target],
...
)
node_size[target]
is a constant value. Hovewer, while creating bounding boxes of text labels, it would be nice to have a support for rectangular nodes that encloses text labels [1]. Also, netgraph
lacks support for dynamic recomputation of the offset
while dragging source nodes in order to point arrows of edges to exact positions of bounding boxes of rectangles ot text labels (it should remain unique for each edge that points to the same node)[2]. Currently, it is able to point arrows only to specific offsets of each node that remains constant. I'm able to write code for both [1] and [2] and I can share it but I'm not sure if it's possible to allow each node artist to have attributes responsible for different height and width, not node_size
only.
Hi, thanks for raising the issue and explaining in detail what you mean. I get it now. ;-)
to allow each node artist to have attributes responsible for different height and width
Strictly speaking, even that would not be enough, as node artists can be triangles, for example.
The more I think about it, the more it seems that we might want to emulate matplotlib's FancyArrowPatch
, which supports a patchA
and a patchB
parameter. These can be arbitrary patch objects, and matplotlib uses them to clip the path that then forms the midline of the arrow.
I've spent more time studying source code of netgraph
this week. In conclusion, I've found that node and edge artist objects are inherited from matplotlib.patches.PathPatch
class. It doesn't look to have support for pointing edges to any kind of labels. matplotlib.patches.PathPatch
is also scalable unlike text of node labels. This might be another issue. So, indeed, the only remaining option is FancyArrowPatch like in my answer. I'm OK with rectangular shapes at the moment.
I guess this functionality requires a lot of changes of current version. Could we expect them in the future versions of netgraph
?
It doesn't look to have support for pointing edges to any kind of labels.
That is correct. Edges point to nodes, not the node labels. Netgraph supports placing node labels with an offset, i.e. outside of the node artist (/PathPatch), so pointing edges at node labels would not make much sense in the context of the rest of the code base.
However, by default, iff the node labels are plotted centered on the node artists (i.e. without an offset), netgraph scales the font size of node labels such that all labels fit inside their node artists. Hence for me implementing this feature is equivalent to
- supporting arbitrary node shapes, while
- handling the node and edge artist overlaps more precisely.
I think you are imagining plotting the graph without any node artists and using the text bounding box as a node artist replacement. However, that would break pretty much everything else in the current code base (e.g. everything interactive), so any support for that will only ever be accidental.
I guess this functionality requires a lot of changes of current version.
If it is implemented the way that I am imagining it, I don't think it is too bad. I suspect almost all of the changes are isolated to _artists.py so the problem is quite self-contained.
-
NodeArtist
in _artists.py would need a redesign to support arbitrary node shapes. - The
offset
parameter inEdgeartist
would have to be replaced by references to the artists of the source and target nodes of that edge. Then the path of the node artists patches could be used to clip the midline path inEdgeArtist._update_path
. IIRC, matplotlibPatch
instances have aclip_path
method so that shouldn't be too hard.
Outside of _artists.py, I only expect minor changes in _main.py, specifically
-
BaseGraph._get_font_size
would need a different way to determine the font size of a node label such that it fits the node artist -
BaseGraph.draw_edges
would have to pass in the source and target node artists toEdgeArtist
, which would be trivial.
That should be it, mostly?
Could we expect them in the future versions of netgraph?
It's fairly high on my netgraph todo list but I have a lot of work on my plate (of the type that pays bills) and my firstborn is due in a month. So if it doesn't happen in the next couple of weeks, it might be quite some time until I have enough head space to continue development on netgraph.
On the dev
branch,
- nodes can now have arbitrary shapes (specified by
matplotlib.path.Path
instances), and - edges connect precisely to their targets for arbitrary node shapes.
This should allow you to create rectangular nodes, that can then serve as text boxes.
I am in the process of preparing a new major release, and it hence will be some time until dev
will get merged into the master
branch. To install the dev
branch, use:
pip install https://github.com/paulbrodersen/netgraph/archive/dev.zip