paulbrodersen / netgraph

Publication-quality network visualisations in python
GNU General Public License v3.0
667 stars 40 forks source link

Support for joining edges with bounding boxes of text labels of nodes #37

Closed loijord closed 1 year ago

loijord commented 2 years ago

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.

paulbrodersen commented 2 years ago

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.

loijord commented 2 years ago

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?

paulbrodersen commented 2 years ago

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

  1. supporting arbitrary node shapes, while
  2. 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.

Outside of _artists.py, I only expect minor changes in _main.py, specifically

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.

paulbrodersen commented 1 year ago

On the dev branch,

1) nodes can now have arbitrary shapes (specified by matplotlib.path.Path instances), and 2) 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