iplotx 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
iplotx/label.py CHANGED
@@ -1,3 +1,7 @@
1
+ """
2
+ Module for label collection in iplotx.
3
+ """
4
+
1
5
  from typing import (
2
6
  Optional,
3
7
  Sequence,
@@ -26,13 +30,28 @@ from .utils.matplotlib import (
26
30
  )
27
31
  )
28
32
  class LabelCollection(mpl.artist.Artist):
33
+ """Collection of labels for iplotx with styles.
34
+
35
+ NOTE: This class is not a subclass of `mpl.collections.Collection`, although in some ways items
36
+ behaves like one. It is named LabelCollection quite literally to indicate it contains a list of
37
+ labels for vertices, edges, etc.
38
+ """
39
+
29
40
  def __init__(
30
41
  self,
31
42
  labels: Sequence[str],
32
43
  style: Optional[dict[str, dict]] = None,
33
44
  offsets: Optional[np.ndarray] = None,
34
45
  transform: mpl.transforms.Transform = mpl.transforms.IdentityTransform(),
35
- ):
46
+ ) -> None:
47
+ """Initialize a collection of labels.
48
+
49
+ Parameters:
50
+ labels: A sequence of labels to be displayed.
51
+ style: A dictionary of styles to apply to the labels. The keys are style properties.
52
+ offsets: A sequence of offsets for each label, specifying the position of the label.
53
+ transform: A transform to apply to the labels. This is usually ax.transData.
54
+ """
36
55
  self._labels = labels
37
56
  self._offsets = offsets if offsets is not None else np.zeros((len(labels), 2))
38
57
  self._style = style
@@ -41,19 +60,25 @@ class LabelCollection(mpl.artist.Artist):
41
60
  self.set_transform(transform)
42
61
  self._create_artists()
43
62
 
44
- def get_children(self):
63
+ def get_children(self) -> tuple[mpl.artist.Artist]:
64
+ """Get the children of this artist, which are the label artists."""
45
65
  return tuple(self._labelartists)
46
66
 
47
- def set_figure(self, figure):
48
- super().set_figure(figure)
67
+ def set_figure(self, fig) -> None:
68
+ """Set the figure of this artist.
69
+
70
+ Parameters:
71
+ fig: The figure to set.
72
+ """
73
+ super().set_figure(fig)
49
74
  for child in self.get_children():
50
- child.set_figure(figure)
51
- self._update_offsets(dpi=figure.dpi)
75
+ child.set_figure(fig)
76
+ self._update_offsets(dpi=fig.dpi)
52
77
 
53
- def _get_margins_with_dpi(self, dpi=72.0):
78
+ def _get_margins_with_dpi(self, dpi: float = 72.0) -> np.ndarray:
54
79
  return self._margins * dpi / 72.0
55
80
 
56
- def _create_artists(self):
81
+ def _create_artists(self) -> None:
57
82
  style = copy_with_deep_values(self._style) if self._style is not None else {}
58
83
  transform = self.get_transform()
59
84
 
@@ -83,12 +108,13 @@ class LabelCollection(mpl.artist.Artist):
83
108
  self._labelartists = arts
84
109
  self._margins = np.array(margins)
85
110
 
86
- def _update_offsets(self, dpi=72.0):
111
+ def _update_offsets(self, dpi: float = 72.0) -> None:
87
112
  """Update offsets including margins."""
88
113
  offsets = self._adjust_offsets_for_margins(self._offsets, dpi=dpi)
89
114
  self.set_offsets(offsets)
90
115
 
91
- def get_offsets(self):
116
+ def get_offsets(self) -> np.ndarray:
117
+ """Get the positions (offsets) of the labels."""
92
118
  return self._offsets
93
119
 
94
120
  def _adjust_offsets_for_margins(self, offsets, dpi=72.0):
@@ -100,13 +126,22 @@ class LabelCollection(mpl.artist.Artist):
100
126
  offsets = trans_inv(trans(offsets) + margins)
101
127
  return offsets
102
128
 
103
- def set_offsets(self, offsets):
104
- """Set positions (offsets) of the labels."""
129
+ def set_offsets(self, offsets) -> None:
130
+ """Set positions (offsets) of the labels.
131
+
132
+ Parameters:
133
+ offsets: A sequence of offsets for each label, specifying the position of the label.
134
+ """
105
135
  self._offsets = np.asarray(offsets)
106
136
  for art, offset in zip(self._labelartists, self._offsets):
107
137
  art.set_position((offset[0], offset[1]))
108
138
 
109
- def set_rotations(self, rotations):
139
+ def set_rotations(self, rotations: Sequence[float]) -> None:
140
+ """Set the rotations of the labels.
141
+
142
+ Parameters:
143
+ rotations: A sequence of rotations in radians for each label.
144
+ """
110
145
  for art, rotation in zip(self._labelartists, rotations):
111
146
  rot_deg = 180.0 / np.pi * rotation
112
147
  # Force the font size to be upwards
@@ -114,7 +149,7 @@ class LabelCollection(mpl.artist.Artist):
114
149
  art.set_rotation(rot_deg)
115
150
 
116
151
  @_stale_wrapper
117
- def draw(self, renderer):
152
+ def draw(self, renderer) -> None:
118
153
  """Draw each of the children, with some buffering mechanism."""
119
154
  if not self.get_visible():
120
155
  return
iplotx/layout.py CHANGED
@@ -18,7 +18,8 @@ def compute_tree_layout(
18
18
  Parameters:
19
19
  tree: The tree to compute the layout for.
20
20
  layout: The name of the layout, e.g. "horizontal" or "radial".
21
- orientation: The orientation of the layout, e.g. "right", "left", "descending", or "ascending".
21
+ orientation: The orientation of the layout, e.g. "right", "left", "descending", or
22
+ "ascending".
22
23
 
23
24
  Returns:
24
25
  A layout dictionary with node positions.
@@ -71,7 +72,6 @@ def _horizontal_tree_layout_right(
71
72
  # Set the x values for vertices
72
73
  layout[root_fun(tree)][0] = 0
73
74
  for node in preorder_fun(tree):
74
- x0, y0 = layout[node]
75
75
  for child in children_fun(node):
76
76
  bl = branch_length_fun(child)
77
77
  if bl is None:
@@ -93,7 +93,7 @@ def _horizontal_tree_layout(
93
93
  layout = _horizontal_tree_layout_right(tree, **kwargs)
94
94
 
95
95
  if orientation == "left":
96
- for key, value in layout.items():
96
+ for key in layout:
97
97
  layout[key][0] *= -1
98
98
  return layout
99
99
 
iplotx/network.py CHANGED
@@ -128,12 +128,12 @@ class NetworkArtist(mpl.artist.Artist):
128
128
  if len(layout) == 0:
129
129
  return mpl.transforms.Bbox([[0, 0], [1, 1]])
130
130
 
131
- if self._vertices is not None:
132
- bbox = self._vertices.get_datalim(transData)
133
-
134
- if self._edges is not None:
135
- edge_bbox = self._edges.get_datalim(transData)
136
- bbox = mpl.transforms.Bbox.union([bbox, edge_bbox])
131
+ bbox = mpl.transforms.Bbox.union(
132
+ [
133
+ self._vertices.get_datalim(transData),
134
+ self._edges.get_datalim(transData),
135
+ ]
136
+ )
137
137
 
138
138
  bbox = bbox.expanded(sw=(1.0 + pad), sh=(1.0 + pad))
139
139
  return bbox
@@ -162,6 +162,9 @@ class NetworkArtist(mpl.artist.Artist):
162
162
 
163
163
  self._vertices = VertexCollection(
164
164
  layout=self.get_layout(),
165
+ layout_coordinate_system=self._ipx_internal_data.get(
166
+ "layout_coordinate_system", "cartesian"
167
+ ),
165
168
  style=get_style(".vertex"),
166
169
  labels=self._get_label_series("vertex"),
167
170
  transform=self.get_transform(),
@@ -238,8 +241,6 @@ class NetworkArtist(mpl.artist.Artist):
238
241
  edgepatches,
239
242
  vertex_ids=adjacent_vertex_ids,
240
243
  vertex_collection=self._vertices,
241
- layout=self.get_layout(),
242
- layout_coordinate_system="cartesian",
243
244
  labels=labels,
244
245
  transform=self.get_offset_transform(),
245
246
  style=edge_style,
iplotx/style.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from typing import (
2
2
  Any,
3
- Never,
4
3
  Optional,
5
4
  Sequence,
6
5
  )
@@ -23,7 +22,7 @@ style_leaves = (
23
22
  "zorder",
24
23
  "tension",
25
24
  "looptension",
26
- "lloopmaxangle",
25
+ "loopmaxangle",
27
26
  "rotate",
28
27
  "marker",
29
28
  "waypoints",
@@ -37,6 +36,15 @@ style_leaves = (
37
36
  "ports",
38
37
  )
39
38
 
39
+ # These properties are not allowed to be rotated (global throughout the graph).
40
+ # This might change in the future as the API improves.
41
+ nonrotating_leaves = (
42
+ "offset",
43
+ "looptension",
44
+ "loopmaxangle",
45
+ "vertexpadding",
46
+ )
47
+
40
48
 
41
49
  default = {
42
50
  "vertex": {
@@ -247,7 +255,7 @@ def use(style: Optional[str | dict | Sequence] = None, **kwargs):
247
255
  raise
248
256
 
249
257
 
250
- def reset() -> Never:
258
+ def reset() -> None:
251
259
  """Reset to default style."""
252
260
  global current
253
261
  current = copy_with_deep_values(styles["default"])
@@ -276,7 +284,7 @@ def context(style: Optional[str | dict | Sequence] = None, **kwargs):
276
284
 
277
285
  def unflatten_style(
278
286
  style_flat: dict[str, str | dict | int | float],
279
- ) -> Never:
287
+ ) -> None:
280
288
  """Convert a flat or semi-flat style into a fully structured dict.
281
289
 
282
290
  Parameters:
@@ -326,7 +334,7 @@ def rotate_style(
326
334
  style: dict[str, Any],
327
335
  index: Optional[int] = None,
328
336
  key: Optional[Hashable] = None,
329
- props: Sequence[str] = style_leaves,
337
+ props: Optional[Sequence[str]] = None,
330
338
  ) -> dict[str, Any]:
331
339
  """Rotate leaves of a style for a certain index or key.
332
340
 
@@ -338,7 +346,8 @@ def rotate_style(
338
346
  props: The properties to rotate, usually all leaf properties.
339
347
 
340
348
  Returns:
341
- A style with rotated leaves, which describes the properties of a single element (e.g. vertex).
349
+ A style with rotated leaves, which describes the properties of a single element (e.g.
350
+ vertex).
342
351
 
343
352
  Example:
344
353
  >>> style = {'vertex': {'size': [10, 20]}}
@@ -350,6 +359,9 @@ def rotate_style(
350
359
  "At least one of 'index' or 'key' must be provided to rotate_style."
351
360
  )
352
361
 
362
+ if props is None:
363
+ props = tuple(prop for prop in style_leaves if prop not in nonrotating_leaves)
364
+
353
365
  style = copy_with_deep_values(style)
354
366
 
355
367
  for prop in props:
iplotx/tree.py CHANGED
@@ -2,6 +2,7 @@ from typing import (
2
2
  Optional,
3
3
  Sequence,
4
4
  )
5
+ from collections.abc import Hashable
5
6
 
6
7
  import numpy as np
7
8
  import pandas as pd
@@ -26,6 +27,9 @@ from .edge import (
26
27
  EdgeCollection,
27
28
  make_stub_patch as make_undirected_edge_patch,
28
29
  )
30
+ from .label import (
31
+ LabelCollection,
32
+ )
29
33
  from .network import (
30
34
  _update_from_internal,
31
35
  )
@@ -50,13 +54,31 @@ class TreeArtist(mpl.artist.Artist):
50
54
  layout="horizontal",
51
55
  orientation="right",
52
56
  directed: bool | str = False,
53
- vertex_labels: Optional[list | dict | pd.Series] = None,
57
+ vertex_labels: Optional[
58
+ bool | list[str] | dict[Hashable, str] | pd.Series
59
+ ] = None,
54
60
  edge_labels: Optional[Sequence] = None,
55
61
  transform: mpl.transforms.Transform = mpl.transforms.IdentityTransform(),
56
62
  offset_transform: Optional[mpl.transforms.Transform] = None,
57
63
  ):
58
- self.tree = tree
64
+ """Initialize the TreeArtist.
65
+
66
+ Parameters:
67
+ tree: The tree to plot.
68
+ layout: The layout to use for the tree. Can be "horizontal", "vertical", or "radial".
69
+ orientation: The orientation of the tree layout. Can be "right" or "left" (for
70
+ horizontal and radial layouts) and "descending" or "ascending" (for vertical
71
+ layouts).
72
+ directed: Whether the tree is directed. Can be a boolean or a string with the
73
+ following choices: "parent" or "child".
74
+ vertex_labels: Labels for the vertices. Can be a list, dictionary, or pandas Series.
75
+ edge_labels: Labels for the edges. Can be a sequence of strings.
76
+ transform: The transform to apply to the tree artist. This is usually the identity.
77
+ offset_transform: The offset transform to apply to the tree artist. This is
78
+ usually `ax.transData`.
79
+ """
59
80
 
81
+ self.tree = tree
60
82
  self._ipx_internal_data = ingest_tree_data(
61
83
  tree,
62
84
  layout,
@@ -80,13 +102,23 @@ class TreeArtist(mpl.artist.Artist):
80
102
  self._add_vertices()
81
103
  self._add_edges()
82
104
 
83
- def get_children(self):
105
+ def get_children(self) -> tuple[mpl.artist.Artist]:
106
+ """Get the children of this artist.
107
+
108
+ Returns:
109
+ The artists for vertices and edges.
110
+ """
84
111
  return (self._vertices, self._edges)
85
112
 
86
- def set_figure(self, figure):
87
- super().set_figure(figure)
113
+ def set_figure(self, fig) -> None:
114
+ """Set the figure for this artist and its children.
115
+
116
+ Parameters:
117
+ fig: the figure to set for this artist and its children.
118
+ """
119
+ super().set_figure(fig)
88
120
  for child in self.get_children():
89
- child.set_figure(figure)
121
+ child.set_figure(fig)
90
122
 
91
123
  def get_offset_transform(self):
92
124
  """Get the offset transform (for vertices/edges)."""
@@ -132,43 +164,43 @@ class TreeArtist(mpl.artist.Artist):
132
164
  bbox = bbox.expanded(sw=(1.0 + pad), sh=(1.0 + pad))
133
165
  return bbox
134
166
 
135
- def _get_label_series(self, kind):
167
+ def _get_label_series(self, kind: str) -> Optional[pd.Series]:
136
168
  if "label" in self._ipx_internal_data[f"{kind}_df"].columns:
137
169
  return self._ipx_internal_data[f"{kind}_df"]["label"]
138
170
  else:
139
171
  return None
140
172
 
141
- def get_vertices(self):
173
+ def get_vertices(self) -> VertexCollection:
142
174
  """Get VertexCollection artist."""
143
175
  return self._vertices
144
176
 
145
- def get_edges(self):
177
+ def get_edges(self) -> EdgeCollection:
146
178
  """Get EdgeCollection artist."""
147
179
  return self._edges
148
180
 
149
- def get_vertex_labels(self):
181
+ def get_vertex_labels(self) -> LabelCollection:
150
182
  """Get list of vertex label artists."""
151
183
  return self._vertices.get_labels()
152
184
 
153
- def get_edge_labels(self):
185
+ def get_edge_labels(self) -> LabelCollection:
154
186
  """Get list of edge label artists."""
155
187
  return self._edges.get_labels()
156
188
 
157
- def _add_vertices(self):
189
+ def _add_vertices(self) -> None:
158
190
  """Add vertices to the tree."""
159
191
  self._vertices = VertexCollection(
160
192
  layout=self.get_layout(),
161
- style=get_style(".vertex"),
162
- labels=self._get_label_series("vertex"),
163
193
  layout_coordinate_system=self._ipx_internal_data.get(
164
194
  "layout_coordinate_system",
165
195
  "catesian",
166
196
  ),
197
+ style=get_style(".vertex"),
198
+ labels=self._get_label_series("vertex"),
167
199
  transform=self.get_transform(),
168
200
  offset_transform=self.get_offset_transform(),
169
201
  )
170
202
 
171
- def _add_edges(self):
203
+ def _add_edges(self) -> None:
172
204
  """Add edges to the network artist.
173
205
 
174
206
  NOTE: UndirectedEdgeCollection and ArrowCollection are both subclasses of
@@ -256,11 +288,6 @@ class TreeArtist(mpl.artist.Artist):
256
288
  edgepatches,
257
289
  vertex_ids=adjacent_vertex_ids,
258
290
  vertex_collection=self._vertices,
259
- layout=self.get_layout(kind="vertex"),
260
- layout_coordinate_system=self._ipx_internal_data.get(
261
- "layout_coordinate_system",
262
- "cartesian",
263
- ),
264
291
  labels=labels,
265
292
  transform=self.get_offset_transform(),
266
293
  style=edge_style,
@@ -270,7 +297,7 @@ class TreeArtist(mpl.artist.Artist):
270
297
  self._edges.set_array(colorarray)
271
298
 
272
299
  @_stale_wrapper
273
- def draw(self, renderer):
300
+ def draw(self, renderer) -> None:
274
301
  """Draw each of the children, with some buffering mechanism."""
275
302
  if not self.get_visible():
276
303
  return
iplotx/typing.py CHANGED
@@ -1,8 +1,17 @@
1
+ """
2
+ Typing hints for iplotx.
3
+
4
+ Some of these types are legit, others are just Any but renamed to improve readability throughout
5
+ the codebase.
6
+ """
7
+
1
8
  from typing import (
2
9
  Union,
3
10
  Sequence,
4
11
  Any,
12
+ TypeVar,
5
13
  )
14
+ from collections.abc import Hashable
6
15
  import numpy as np
7
16
  import pandas as pd
8
17
 
@@ -34,3 +43,13 @@ GroupingType = Union[
34
43
  # igraph.clustering.Cover,
35
44
  # igraph.clustering.VertexCover,
36
45
  ]
46
+
47
+
48
+ T = TypeVar("T")
49
+ LeafProperty = Union[
50
+ T,
51
+ Sequence[T],
52
+ dict[Hashable, T],
53
+ ]
54
+
55
+ Pair = tuple[T, T]
iplotx/version.py CHANGED
@@ -2,4 +2,4 @@
2
2
  iplotx version information module.
3
3
  """
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.2.1"
iplotx/vertex.py CHANGED
@@ -6,7 +6,6 @@ from typing import (
6
6
  Optional,
7
7
  Sequence,
8
8
  Any,
9
- Never,
10
9
  )
11
10
  import warnings
12
11
  import numpy as np
@@ -70,20 +69,21 @@ class VertexCollection(PatchCollection):
70
69
  self._index = layout.index
71
70
  self._style = style
72
71
  self._labels = labels
72
+ self._layout = layout
73
+ self._layout_coordinate_system = layout_coordinate_system
73
74
 
74
75
  # Create patches from structured data
75
- patches, offsets, sizes, kwargs2 = self._init_vertex_patches(
76
- layout,
77
- layout_coordinate_system=layout_coordinate_system,
78
- )
76
+ patches, sizes, kwargs2 = self._init_vertex_patches()
79
77
 
80
78
  kwargs.update(kwargs2)
81
- kwargs["offsets"] = offsets
82
79
  kwargs["match_original"] = True
83
80
 
84
81
  # Pass to PatchCollection constructor
85
82
  super().__init__(patches, *args, **kwargs)
86
83
 
84
+ # Set offsets in coordinate system
85
+ self._update_offsets_from_layout()
86
+
87
87
  # Compute _transforms like in _CollectionWithScales for dpi issues
88
88
  self.set_sizes(sizes)
89
89
 
@@ -100,7 +100,7 @@ class VertexCollection(PatchCollection):
100
100
  children.append(self._label_collection)
101
101
  return tuple(children)
102
102
 
103
- def set_figure(self, fig) -> Never:
103
+ def set_figure(self, fig) -> None:
104
104
  """Set the figure for this artist and all children."""
105
105
  super().set_figure(fig)
106
106
  self.set_sizes(self._sizes, self.get_figure(root=True).dpi)
@@ -123,7 +123,7 @@ class VertexCollection(PatchCollection):
123
123
  """Get vertex sizes (max of width and height), scaled by dpi."""
124
124
  return self._transforms[:, 0, 0]
125
125
 
126
- def set_sizes(self, sizes, dpi=72.0):
126
+ def set_sizes(self, sizes, dpi: float = 72.0) -> None:
127
127
  """Set vertex sizes.
128
128
 
129
129
  This rescales the current vertex symbol/path linearly, using this
@@ -146,9 +146,70 @@ class VertexCollection(PatchCollection):
146
146
  get_size = get_sizes
147
147
  set_size = set_sizes
148
148
 
149
- def _init_vertex_patches(
150
- self, vertex_layout_df, layout_coordinate_system="cartesian"
151
- ):
149
+ def get_layout(self) -> pd.DataFrame:
150
+ """Get the vertex layout.
151
+
152
+ Returns:
153
+ The vertex layout as a DataFrame.
154
+ """
155
+ return self._layout
156
+
157
+ def get_layout_coordinate_system(self) -> str:
158
+ """Get the layout coordinate system.
159
+
160
+ Returns:
161
+ Name of the layout coordinate system, e.g. "cartesian" or "polar".
162
+ """
163
+ return self._layout_coordinate_system
164
+
165
+ def get_offsets(self, ignore_layout: bool = True) -> np.ndarray:
166
+ """Get the vertex offsets.
167
+
168
+ Parameters:
169
+ ignore_layout: If True, return the matplotlib Artist._offsets directly, ignoring the
170
+ layout coordinate system. If False, it's equivalent to get_layout().values.
171
+
172
+ Returns:
173
+ The vertex offsets as a 2D numpy array.
174
+
175
+ Note: It is best for users to *not* ignore the layout coordinate system, as it may lead
176
+ to inconsistencies. However, some internal matplotlib functions require the default
177
+ signature of this function to look at the vanilla offsets, hence the default parameters.
178
+ """
179
+ if not ignore_layout:
180
+ return self.get_layout().values
181
+ else:
182
+ return self._offsets
183
+
184
+ def _update_offsets_from_layout(self) -> None:
185
+ """Update offsets in matplotlib coordinates from the layout DataFrame."""
186
+ if self._layout_coordinate_system == "cartesian":
187
+ self._offsets = self._layout.values
188
+ elif self._layout_coordinate_system == "polar":
189
+ # Convert polar coordinates (r, theta) to cartesian (x, y)
190
+ r = self._layout.iloc[:, 0].values
191
+ theta = self._layout.iloc[:, 1].values
192
+ if self._offsets is None:
193
+ self._offsets = np.zeros((len(r), 2))
194
+ self._offsets[:, 0] = r * np.cos(theta)
195
+ self._offsets[:, 1] = r * np.sin(theta)
196
+ else:
197
+ raise ValueError(
198
+ f"Layout coordinate system not supported: {self._layout_coordinate_system}."
199
+ )
200
+
201
+ def set_offsets(self, offsets: np.ndarray) -> None:
202
+ """Set the vertex positions/offsets in layout coordinates.
203
+
204
+ Parameters:
205
+ offsets: Array of coordinates in the layout coordinate system. For polar layouts,
206
+ these should be in the form of (r, theta) pairs.
207
+ """
208
+ self._layout.values[:] = offsets
209
+ self._update_offsets_from_layout()
210
+ self.stale = True
211
+
212
+ def _init_vertex_patches(self):
152
213
  style = self._style or {}
153
214
  if "cmap" in style:
154
215
  cmap_fun = _build_cmap_fun(
@@ -164,29 +225,16 @@ class VertexCollection(PatchCollection):
164
225
  "No labels found, cannot resize vertices based on labels."
165
226
  )
166
227
  style["size"] = get_style("default.vertex")["size"]
167
- else:
168
- vertex_labels = self._labels
169
228
 
170
229
  if "cmap" in style:
171
230
  colorarray = []
172
231
  patches = []
173
- offsets = []
174
232
  sizes = []
175
- for i, (vid, row) in enumerate(vertex_layout_df.iterrows()):
176
- # Centre of the vertex
177
- offset = list(row.values)
178
-
179
- # Transform to cartesian coordinates if needed
180
- if layout_coordinate_system == "polar":
181
- r, theta = offset
182
- offset = [r * np.cos(theta), r * np.sin(theta)]
183
-
184
- offsets.append(offset)
185
-
186
- if style.get("size") == "label":
233
+ for i, (vid, row) in enumerate(self._layout.iterrows()):
234
+ if style.get("size", 20) == "label":
187
235
  # NOTE: it's ok to overwrite the dict here
188
236
  style["size"] = _get_label_width_height(
189
- str(vertex_labels[vid]), **style.get("label", {})
237
+ str(self._labels[vid]), **style.get("label", {})
190
238
  )
191
239
 
192
240
  stylei = rotate_style(style, index=i, key=vid)
@@ -207,7 +255,7 @@ class VertexCollection(PatchCollection):
207
255
  kwargs["cmap"] = style["cmap"]
208
256
  kwargs["norm"] = norm
209
257
 
210
- return patches, offsets, sizes, kwargs
258
+ return patches, sizes, kwargs
211
259
 
212
260
  def _compute_label_collection(self):
213
261
  transform = self.get_offset_transform()
@@ -230,6 +278,12 @@ class VertexCollection(PatchCollection):
230
278
  )
231
279
 
232
280
  def get_labels(self):
281
+ """Get the vertex labels.
282
+
283
+ Returns:
284
+ The artist with the LabelCollection.
285
+ """
286
+
233
287
  if hasattr(self, "_label_collection"):
234
288
  return self._label_collection
235
289
  else:
@@ -280,7 +334,8 @@ def make_patch(
280
334
 
281
335
  # Size of vertices is determined in self._transforms, which scales with dpi, rather than here,
282
336
  # so normalise by the average dimension (btw x and y) to keep the ratio of the marker.
283
- # If you check in get_sizes, you will see that rescaling also happens with the max of width and height.
337
+ # If you check in get_sizes, you will see that rescaling also happens with the max of width
338
+ # and height.
284
339
  size = np.asarray(size, dtype=float)
285
340
  size_max = size.max()
286
341
  if size_max > 0: