Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bbe93df
First blobs of code
iosonofabio Apr 4, 2023
df01256
A bit more logic
iosonofabio Apr 4, 2023
bf3a183
Move more logic to artist
iosonofabio Apr 4, 2023
7dc40b3
Container artist with children creates, but fails to show
iosonofabio Apr 5, 2023
e310f20
Forwarder as in grave
iosonofabio Apr 5, 2023
33e57b5
Remove unused import
iosonofabio Apr 5, 2023
794410e
Injected axes into builders should be used for transData
iosonofabio Apr 5, 2023
6e24ea6
Working except for zorder
iosonofabio Apr 5, 2023
9121dbb
Manual management of zorder
iosonofabio Apr 5, 2023
8e63abd
zorder in the draw function makes children more consistent
iosonofabio Apr 5, 2023
9bb3962
Return artist in group hull and speed up sorting for zorder
iosonofabio Apr 5, 2023
59e2ce5
Update a few test baseline images, which were manually verified
iosonofabio Apr 5, 2023
74cdbf8
Remove PathCollection TODOs
iosonofabio Apr 5, 2023
4c10be2
Check contains
iosonofabio Apr 5, 2023
05c7437
Revert test image
iosonofabio Apr 5, 2023
9f660d4
mark_groups now works, update baseline test images
iosonofabio Apr 5, 2023
8a7f368
Vertex label offset
iosonofabio Apr 6, 2023
a57011d
Correct logic in draw
iosonofabio Apr 6, 2023
c8ef817
Try new conditional import for matplotlib
iosonofabio Apr 6, 2023
5659847
Try again with mpl imports
iosonofabio Apr 6, 2023
495ce27
New try for import of Artist
iosonofabio Apr 6, 2023
db97952
matplotlib artist: Graph.set
iosonofabio Apr 7, 2023
c261f28
Add specific set methods via decorator
iosonofabio Apr 8, 2023
cfdbe4a
Add docs on new feature in example from gallery
iosonofabio Apr 8, 2023
de7ebe5
Merge remote-tracking branch 'igraph/main' into containerartist
iosonofabio Apr 8, 2023
5972fde
fix: remove unused _Unset class and _UNSET instance
ntamas Apr 21, 2023
e8ab5c5
refactor: renamed Matplotlib Graph artist to GraphArtist
ntamas Apr 21, 2023
b3087e9
Merge branch 'main' into containerartist
ntamas Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions doc/examples_sphinx-gallery/visual_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,25 @@
# default, you can use igraph's `configuration instance
# :class:`igraph.configuration.Configuration`. A quick example on how to use
# it can be found here: :ref:`tutorials-configuration`.

# %%
# In the matplotlib backend, igraph creates a special container
# :class:`igraph.drawing.matplotlib.graph.GraphArtist` which is a matplotlib Artist
# and the first child of the target Axes. That object can be used to customize
# the plot appearance after the initial drawing, e.g.:
g = ig.Graph.Barabasi(n=30, m=1)
fig, ax = plt.subplots()
ig.plot(g, target=ax)
artist = ax.get_children()[0]
# Option 1:
artist.set(vertex_color="blue")
# Option 2:
artist.set_vertex_color("blue")
plt.show()

# %%
# .. note::
# The ``artist.set`` method can be used to change multiple properties at
# once and is generally more efficient than multiple calls to specific
# ``artist.set_...` methods.

5 changes: 4 additions & 1 deletion src/igraph/drawing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,16 @@ def plot(obj, target=None, bbox=(0, 0, 600, 600), *args, **kwds):
warn("%s does not support plotting" % (obj,))
return
else:
plotter(
result = plotter(
backend,
target,
palette=palette,
*args,
**kwds,
)
# NOTE: for matplotlib, result is the container Artist. It would be
# good to return this instead of target, like we do for Cairo.
# However, that breaks API so let's wait for a major release

if save_path is not None:
if backend == "matplotlib":
Expand Down
2 changes: 1 addition & 1 deletion src/igraph/drawing/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,4 +555,4 @@ def __plot__(self, backend, context, *args, **kwds):
"drawer_factory",
DrawerDirectory.resolve(self, backend)(context),
)
drawer.draw(self, *args, **kwds)
return drawer.draw(self, *args, **kwds)
30 changes: 20 additions & 10 deletions src/igraph/drawing/matplotlib/edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ class VisualEdgeBuilder(AttributeCollectorBase):
width = 2.0
background = None
align_label = False
zorder = 1

return VisualEdgeBuilder

def draw_directed_edge(self, edge, src_vertex, dest_vertex):
if src_vertex == dest_vertex: # TODO
if src_vertex == dest_vertex:
return self.draw_loop_edge(edge, src_vertex)

ax = self.context
Expand Down Expand Up @@ -163,16 +164,18 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex):
path["codes"].append("LINETO")

# Draw the edge
stroke = mpl.patches.PathPatch(
arrowshaft = mpl.patches.PathPatch(
mpl.path.Path(
path["vertices"],
codes=[getattr(mpl.path.Path, x) for x in path["codes"]],
),
edgecolor=edge.color,
facecolor="none",
linewidth=edge.width,
zorder=edge.zorder,
transform=ax.transData,
clip_on=True,
)
ax.add_patch(stroke)

# Draw the arrow head
arrowhead = mpl.patches.Polygon(
Expand All @@ -184,8 +187,11 @@ def draw_directed_edge(self, edge, src_vertex, dest_vertex):
closed=True,
facecolor=edge.color,
edgecolor="none",
zorder=edge.zorder,
transform=ax.transData,
clip_on=True,
)
ax.add_patch(arrowhead)
return [arrowshaft, arrowhead]

def draw_loop_edge(self, edge, vertex):
"""Draws a loop edge.
Expand All @@ -201,7 +207,7 @@ def draw_loop_edge(self, edge, vertex):
radius = vertex.size * 1.5
center_x = vertex.position[0] + cos(pi / 4) * radius / 2.0
center_y = vertex.position[1] - sin(pi / 4) * radius / 2.0
stroke = mpl.patches.Arc(
art = mpl.patches.Arc(
(center_x, center_y),
radius / 2.0,
radius / 2.0,
Expand All @@ -210,9 +216,11 @@ def draw_loop_edge(self, edge, vertex):
linewidth=edge.width,
facecolor="none",
edgecolor=edge.color,
zorder=edge.zorder,
transform=ax.transData,
clip_on=True,
)
# FIXME: make a PathCollection??
ax.add_patch(stroke)
return [art]

def draw_undirected_edge(self, edge, src_vertex, dest_vertex):
"""Draws an undirected edge.
Expand Down Expand Up @@ -247,14 +255,16 @@ def draw_undirected_edge(self, edge, src_vertex, dest_vertex):
path["vertices"].append(dest_vertex.position)
path["codes"].append("LINETO")

stroke = mpl.patches.PathPatch(
art = mpl.patches.PathPatch(
mpl.path.Path(
path["vertices"],
codes=[getattr(mpl.path.Path, x) for x in path["codes"]],
),
edgecolor=edge.color,
facecolor="none",
linewidth=edge.width,
zorder=edge.zorder,
transform=ax.transData,
clip_on=True,
)
# FIXME: make a PathCollection??
ax.add_artist(stroke)
return [art]
Loading