Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
loijord opened this issue Apr 14, 2022 · 4 comments
Closed

Comments

@loijord
Copy link

loijord commented Apr 14, 2022

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
Copy link
Owner

paulbrodersen commented Apr 14, 2022

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
Copy link
Author

loijord commented Apr 22, 2022

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
Copy link
Owner

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.

  • NodeArtist in _artists.py would need a redesign to support arbitrary node shapes.
  • The offset parameter in Edgeartist 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 in EdgeArtist._update_path. IIRC, matplotlib Patch instances have a clip_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 to EdgeArtist, 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.

@paulbrodersen
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants