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

Different labels for bidirectional arrows #92

Open
jamesbraza opened this issue Jun 5, 2024 · 6 comments
Open

Different labels for bidirectional arrows #92

jamesbraza opened this issue Jun 5, 2024 · 6 comments

Comments

@jamesbraza
Copy link

This code, with netgraph==4.13.2 and matplotlib==3.9.0:

from netgraph import Graph
import matplotlib.pyplot as plt

edges = [("in", "out"), ("out", "in")]
edge_labels = {
    ("in", "out"): 3,
    ("out", "in"): 5,
}
graph = Graph(
    edges, node_labels=True, edge_labels=edge_labels, arrows=True, node_label_offset=(1e-4, 0)
)
plt.show()

Renders like so:

image

We can see it clobbered the 3 label. Any chance we can support bidirectional arrows, that have a different label per direction?

@paulbrodersen
Copy link
Owner

paulbrodersen commented Jun 6, 2024

The text object for label 3 will be there, but the label 5 is occluding it currently.
There are several options to deal with this issue.

  1. Don't plot the labels exactly at the center of the edge (not a great solution, but results in the least changes to the figure).
from netgraph import Graph
import matplotlib.pyplot as plt

edges = [("in", "out"), ("out", "in")]
edge_labels = {
    ("in", "out"): 3,
    ("out", "in"): 5,
}
graph = Graph(edges, node_labels=True, node_label_offset=(1e-4, 0),
              edge_labels=edge_labels, edge_label_position=0.33, arrows=True)

plt.show()

Figure_3

  1. Use a curved edge layout.
from netgraph import Graph
import matplotlib.pyplot as plt

edges = [("in", "out"), ("out", "in")]
edge_labels = {
    ("in", "out"): 3,
    ("out", "in"): 5,
}
graph = Graph(edges, node_labels=True, node_label_offset=(1e-4, 0), edge_labels=edge_labels,
              edge_layout="curved", edge_layout_kwargs=dict(bundle_parallel_edges=False),
              arrows=True)

plt.show()

Figure_1

  1. Use the MultiGraph class, which offsets parallel edges from each other (rather than drawing half-arrows).
from netgraph import MultiGraph
import matplotlib.pyplot as plt

# MultiGraph edges require an additional `key`, to distinguish edges connecting the same nodes in the same direction
edges = [("in", "out", 0), ("out", "in", 0)] 

edge_labels = {
    ("in", "out", 0): 3,
    ("out", "in", 0): 5,
}
graph = MultiGraph(edges, node_labels=True, node_label_offset=(1e-4, 0), edge_labels=edge_labels, arrows=True)
plt.show()

Figure_2

@jamesbraza
Copy link
Author

Oh wow, thank you so much for the excellent answer! That totally clears me up on how to proceed.

I still think it's unideal that the default Graph behavior is one label completely occludes the other (without specifying edge_label_position or edge_layout="curved"). I am wondering if you can somehow adjust the default behavior to be "smarter", or at least log a warning that there's an occlusion taking place.

Maybe it's also worth mentioning MultiDiGraph on https://netgraph.readthedocs.io/en/latest/sphinx_gallery_output/plot_06_labels.html, as it seems relevant to occluded labels

@paulbrodersen
Copy link
Owner

I still think it's unideal that the default Graph behavior is one label completely occludes the other (without specifying edge_label_position or edge_layout="curved").

Agreed. However, I am trying pretty hard to keep things stable, and am hence reluctant to change behaviours that have been the default since version 0.0.0.

or at least log a warning that there's an occlusion taking place.

I will add a section to the tutorial along the lines of my pointers above, and issue a warning pointing to said tutorial, when a user

  1. uses the straight edge layout,
  2. has a directed graph with bi-directional edges (but not a MultiGraph),
  3. both directions are labelled for any of the bi-directional edges, and
  4. edge_label_position is 0.5.

Maybe it's also worth mentioning MultiDiGraph on https://netgraph.readthedocs.io/en/latest/sphinx_gallery_output/plot_06_labels.html, as it seems relevant to occluded labels

So far, only the dev branch implements MultiGraph. The documentation has already been updated, but RTD currently only displays the master branch (I will look into adding the docs for the dev branch, too).

@jamesbraza
Copy link
Author

Sounds good, like your proposal! Thanks 👍

When updating the docs, my request is to include renderings of graphs involving bidirectional arrows. When I was reading the docs, I was visually skimming for examples of bidirectional arrows

@paulbrodersen
Copy link
Owner

paulbrodersen commented Jun 10, 2024

What is missing in basic example #2: directed graphs then?

@jamesbraza
Copy link
Author

What is missing in basic example #2: directed graphs then?

The renderings are great, I really like example 2. If you want to robust-ify it, then maybe add a second visualization showing separate labels on the bidirectional arrows

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