iplotx 1.5.1__py3-none-any.whl → 1.7.0__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/edge/__init__.py +27 -12
- iplotx/edge/geometry.py +16 -2
- iplotx/plotting.py +47 -4
- iplotx/utils/matplotlib.py +5 -0
- iplotx/version.py +1 -1
- {iplotx-1.5.1.dist-info → iplotx-1.7.0.dist-info}/METADATA +5 -5
- {iplotx-1.5.1.dist-info → iplotx-1.7.0.dist-info}/RECORD +8 -8
- {iplotx-1.5.1.dist-info → iplotx-1.7.0.dist-info}/WHEEL +1 -1
iplotx/edge/__init__.py
CHANGED
|
@@ -367,21 +367,13 @@ class EdgeCollection(mpl.collections.PatchCollection):
|
|
|
367
367
|
|
|
368
368
|
# Leaf rotation
|
|
369
369
|
edge_stylei = rotate_style(self._style, index=i, key=(v1, v2))
|
|
370
|
-
if edge_stylei.get("curved", False):
|
|
371
|
-
tension = edge_stylei.get("tension", 5)
|
|
372
|
-
ports = edge_stylei.get("ports", (None, None))
|
|
373
|
-
elif edge_stylei.get("arc", False):
|
|
374
|
-
tension = edge_stylei.get("tension", 1)
|
|
375
|
-
ports = None
|
|
376
|
-
else:
|
|
377
|
-
tension = 0
|
|
378
|
-
ports = None
|
|
379
370
|
|
|
380
371
|
# Scale shrink by dpi
|
|
381
372
|
dpi = self.figure.dpi if hasattr(self, "figure") else 72.0
|
|
382
373
|
shrink = dpi / 72.0 * edge_stylei.pop("shrink", 0)
|
|
383
374
|
|
|
384
|
-
#
|
|
375
|
+
# Edge geometry and waypoints
|
|
376
|
+
# waypoints: False is a synonym for "none"
|
|
385
377
|
waypoints = edge_stylei.get("waypoints", "none")
|
|
386
378
|
if waypoints is False or waypoints is np.False_:
|
|
387
379
|
waypoints = "none"
|
|
@@ -391,10 +383,32 @@ class EdgeCollection(mpl.collections.PatchCollection):
|
|
|
391
383
|
raise ValueError(
|
|
392
384
|
"Could not determine automatically type of edge waypoints.",
|
|
393
385
|
)
|
|
394
|
-
if waypoints != "none":
|
|
395
|
-
ports = edge_stylei.get("ports", (None, None))
|
|
396
386
|
|
|
387
|
+
# Waypoints, curved, and arc have a complex logic
|
|
388
|
+
# TODO: This could be simplified I suppose
|
|
389
|
+
has_waypoints = waypoints != "none"
|
|
390
|
+
curved = edge_stylei.get("curved", False)
|
|
397
391
|
arc = edge_stylei.get("arc", False)
|
|
392
|
+
ports = edge_stylei.get("ports", (None, None))
|
|
393
|
+
|
|
394
|
+
# For now, we establish a hierarchy from the most specialised to
|
|
395
|
+
# the most common cases. Each specialisation silences lower levels
|
|
396
|
+
# Tension and ports are entirely enslaved to the
|
|
397
|
+
# waypoint/arc/curved geometry settings.
|
|
398
|
+
# NOTE: The idea here is to not punish users for slight style
|
|
399
|
+
# inconsistencies that may well stem from fallback libraries
|
|
400
|
+
if has_waypoints:
|
|
401
|
+
tension = 0
|
|
402
|
+
arc = False
|
|
403
|
+
elif arc:
|
|
404
|
+
tension = edge_stylei.get("tension", 1)
|
|
405
|
+
ports = None
|
|
406
|
+
curved = False
|
|
407
|
+
elif curved:
|
|
408
|
+
tension = edge_stylei.get("tension", 5)
|
|
409
|
+
else:
|
|
410
|
+
tension = 0
|
|
411
|
+
ports = None
|
|
398
412
|
|
|
399
413
|
# Compute actual edge path
|
|
400
414
|
path, angles = _compute_edge_path(
|
|
@@ -406,6 +420,7 @@ class EdgeCollection(mpl.collections.PatchCollection):
|
|
|
406
420
|
tension=tension,
|
|
407
421
|
waypoints=waypoints,
|
|
408
422
|
ports=ports,
|
|
423
|
+
curved=curved,
|
|
409
424
|
arc=arc,
|
|
410
425
|
layout_coordinate_system=self._vertex_collection.get_layout_coordinate_system(),
|
|
411
426
|
shrink=shrink,
|
iplotx/edge/geometry.py
CHANGED
|
@@ -239,6 +239,7 @@ def _compute_edge_path_straight(
|
|
|
239
239
|
|
|
240
240
|
def _compute_edge_path_waypoints(
|
|
241
241
|
waypoints,
|
|
242
|
+
curved,
|
|
242
243
|
vcoord_data,
|
|
243
244
|
vpath_fig,
|
|
244
245
|
vsize_fig,
|
|
@@ -277,8 +278,19 @@ def _compute_edge_path_waypoints(
|
|
|
277
278
|
+ vcoord_fig[i]
|
|
278
279
|
)
|
|
279
280
|
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
if not curved:
|
|
282
|
+
points = [vshorts[0]] + list(waypoints) + [vshorts[1]]
|
|
283
|
+
codes = ["MOVETO"] + ["LINETO"] * len(waypoints) + ["LINETO"]
|
|
284
|
+
else:
|
|
285
|
+
points = [vshorts[0]]
|
|
286
|
+
for i, waypoint in enumerate(waypoints):
|
|
287
|
+
if i != 0:
|
|
288
|
+
points.append(0.5 * (points[-1] + waypoint))
|
|
289
|
+
points.append(waypoint)
|
|
290
|
+
points.append(waypoint)
|
|
291
|
+
points.append(vshorts[1])
|
|
292
|
+
codes = ["MOVETO"] + ["CURVE4"] * (len(points) - 1)
|
|
293
|
+
|
|
282
294
|
angles = tuple(thetas)
|
|
283
295
|
|
|
284
296
|
elif waypoints in ("x0y1", "y0x1"):
|
|
@@ -587,6 +599,7 @@ def _compute_edge_path(
|
|
|
587
599
|
tension: float = 0,
|
|
588
600
|
waypoints: str | tuple[float, float] | Sequence[tuple[float, float]] | np.ndarray = "none",
|
|
589
601
|
ports: Pair[Optional[str]] = (None, None),
|
|
602
|
+
curved: bool = False,
|
|
590
603
|
arc: bool = False,
|
|
591
604
|
layout_coordinate_system: str = "cartesian",
|
|
592
605
|
**kwargs,
|
|
@@ -600,6 +613,7 @@ def _compute_edge_path(
|
|
|
600
613
|
if waypoints != "none":
|
|
601
614
|
return _compute_edge_path_waypoints(
|
|
602
615
|
waypoints,
|
|
616
|
+
curved,
|
|
603
617
|
*args,
|
|
604
618
|
layout_coordinate_system=layout_coordinate_system,
|
|
605
619
|
ports=ports,
|
iplotx/plotting.py
CHANGED
|
@@ -20,6 +20,7 @@ from .network import NetworkArtist
|
|
|
20
20
|
from .network.groups import GroupingCollection
|
|
21
21
|
from .tree import TreeArtist
|
|
22
22
|
from .style import context
|
|
23
|
+
from .utils.matplotlib import _heuristic_show
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def network(
|
|
@@ -36,6 +37,7 @@ def network(
|
|
|
36
37
|
margins: float | tuple[float, float] | tuple[float, float, float] = 0,
|
|
37
38
|
strip_axes: bool = True,
|
|
38
39
|
figsize: Optional[tuple[float, float]] = None,
|
|
40
|
+
show: Optional[bool] = None,
|
|
39
41
|
**kwargs,
|
|
40
42
|
) -> list[mpl.artist.Artist]:
|
|
41
43
|
"""Plot this network and/or vertex grouping using the specified layout.
|
|
@@ -70,6 +72,9 @@ def network(
|
|
|
70
72
|
figsize: If ax is None, a new matplotlib Figure is created. This argument specifies
|
|
71
73
|
the (width, height) dimension of the figure in inches. If ax is not None, this
|
|
72
74
|
argument is ignored. If None, the default matplotlib figure size is used.
|
|
75
|
+
show: If True, call plt.show() after plotting. If False, do not call plt.show(). If
|
|
76
|
+
None (default), try to guess based on the environment and do not show in case of
|
|
77
|
+
doubt.
|
|
73
78
|
kwargs: Additional arguments are treated as an alternate way to specify style. If
|
|
74
79
|
both "style" and additional **kwargs are provided, they are both applied in that
|
|
75
80
|
order (style, then **kwargs).
|
|
@@ -78,7 +83,12 @@ def network(
|
|
|
78
83
|
A list of mpl.artist.Artist objects, set as a direct child of the matplotlib Axes.
|
|
79
84
|
The list can have one or two elements, depending on whether you are requesting to
|
|
80
85
|
plot a network, a grouping, or both.
|
|
86
|
+
|
|
87
|
+
NOTE: If your plots are now showing to screen, try passing show=True.
|
|
81
88
|
"""
|
|
89
|
+
if show is None:
|
|
90
|
+
show = _heuristic_show()
|
|
91
|
+
|
|
82
92
|
# Equivalence of node_labels and vertex_labels
|
|
83
93
|
if node_labels is not None:
|
|
84
94
|
vertex_labels = node_labels
|
|
@@ -164,6 +174,9 @@ def network(
|
|
|
164
174
|
if (margins[0] != 0) or (margins[1] != 0) or ((len(margins) == 3) and (margins[2] != 0)):
|
|
165
175
|
ax.margins(*margins)
|
|
166
176
|
|
|
177
|
+
if show:
|
|
178
|
+
plt.show()
|
|
179
|
+
|
|
167
180
|
return artists
|
|
168
181
|
|
|
169
182
|
|
|
@@ -187,6 +200,7 @@ def tree(
|
|
|
187
200
|
margins: float | tuple[float, float] = 0,
|
|
188
201
|
strip_axes: bool = True,
|
|
189
202
|
figsize: Optional[tuple[float, float]] = None,
|
|
203
|
+
show: Optional[bool] = None,
|
|
190
204
|
**kwargs,
|
|
191
205
|
) -> TreeArtist:
|
|
192
206
|
"""Plot a tree using the specified layout.
|
|
@@ -226,13 +240,21 @@ def tree(
|
|
|
226
240
|
figsize: If ax is None, a new matplotlib Figure is created. This argument specifies
|
|
227
241
|
the (width, height) dimension of the figure in inches. If ax is not None, this
|
|
228
242
|
argument is ignored. If None, the default matplotlib figure size is used.
|
|
243
|
+
show: If True, call plt.show() after plotting. If False, do not call plt.show(). If
|
|
244
|
+
None (default), try to guess based on the environment and do not show in case of
|
|
245
|
+
doubt.
|
|
229
246
|
kwargs: Additional arguments are treated as an alternate way to specify style. If
|
|
230
247
|
both "style" and additional **kwargs are provided, they are both applied in that
|
|
231
248
|
order (style, then **kwargs).
|
|
232
249
|
|
|
233
250
|
Returns:
|
|
234
251
|
A TreeArtist object, set as a direct child of the matplotlib Axes.
|
|
252
|
+
|
|
253
|
+
NOTE: If your plots are now showing to screen, try passing show=True.
|
|
235
254
|
"""
|
|
255
|
+
if show is None:
|
|
256
|
+
show = _heuristic_show()
|
|
257
|
+
|
|
236
258
|
# Equivalence of node_labels and vertex_labels
|
|
237
259
|
if node_labels is not None:
|
|
238
260
|
vertex_labels = node_labels
|
|
@@ -270,6 +292,9 @@ def tree(
|
|
|
270
292
|
if (margins[0] != 0) or (margins[1] != 0):
|
|
271
293
|
ax.margins(*margins)
|
|
272
294
|
|
|
295
|
+
if show:
|
|
296
|
+
plt.show()
|
|
297
|
+
|
|
273
298
|
return artist
|
|
274
299
|
|
|
275
300
|
|
|
@@ -285,6 +310,7 @@ def doubletree(
|
|
|
285
310
|
margins: float | tuple[float, float] = 0,
|
|
286
311
|
strip_axes: bool = True,
|
|
287
312
|
figsize: Optional[tuple[float, float]] = None,
|
|
313
|
+
show: Optional[bool] = None,
|
|
288
314
|
) -> tuple[TreeArtist, TreeArtist]:
|
|
289
315
|
"""Visualize two trees facing each other.
|
|
290
316
|
|
|
@@ -306,9 +332,26 @@ def doubletree(
|
|
|
306
332
|
figsize: If ax is None, a new matplotlib Figure is created. This argument specifies
|
|
307
333
|
the (width, height) dimension of the figure in inches. If ax is not None, this
|
|
308
334
|
argument is ignored. If None, the default matplotlib figure size is used.
|
|
335
|
+
show: If True, call plt.show() after plotting. If False, do not call plt.show(). If
|
|
336
|
+
None (default), try to guess based on the environment and do not show in case of
|
|
337
|
+
doubt.
|
|
309
338
|
Returns:
|
|
310
339
|
A tuple with the left and right TreeArtist objects.
|
|
340
|
+
|
|
341
|
+
NOTE: If your plots are now showing to screen, try passing show=True.
|
|
311
342
|
"""
|
|
343
|
+
if show is None:
|
|
344
|
+
show = _heuristic_show()
|
|
345
|
+
|
|
346
|
+
if kwargs_left is None:
|
|
347
|
+
kwargs_left = {}
|
|
348
|
+
if "show" not in kwargs_left:
|
|
349
|
+
kwargs_left["show"] = False
|
|
350
|
+
if kwargs_right is None:
|
|
351
|
+
kwargs_right = {}
|
|
352
|
+
if "show" not in kwargs_right:
|
|
353
|
+
kwargs_right["show"] = False
|
|
354
|
+
|
|
312
355
|
artist1 = tree(
|
|
313
356
|
tree_left,
|
|
314
357
|
layout="horizontal",
|
|
@@ -316,14 +359,11 @@ def doubletree(
|
|
|
316
359
|
ax=ax,
|
|
317
360
|
strip_axes=False,
|
|
318
361
|
figsize=figsize,
|
|
319
|
-
**kwargs_left
|
|
362
|
+
**kwargs_left,
|
|
320
363
|
)
|
|
321
364
|
|
|
322
365
|
ax = artist1.axes
|
|
323
366
|
|
|
324
|
-
if kwargs_right is None:
|
|
325
|
-
kwargs_right = {}
|
|
326
|
-
|
|
327
367
|
had_layout_start = "layout_start" in kwargs_right
|
|
328
368
|
|
|
329
369
|
artist2 = tree(
|
|
@@ -348,6 +388,9 @@ def doubletree(
|
|
|
348
388
|
|
|
349
389
|
_postprocess_axes(ax, [artist1, artist2], strip=strip_axes, ignore_previous=True)
|
|
350
390
|
|
|
391
|
+
if show:
|
|
392
|
+
plt.show()
|
|
393
|
+
|
|
351
394
|
return (artist1, artist2)
|
|
352
395
|
|
|
353
396
|
|
iplotx/utils/matplotlib.py
CHANGED
|
@@ -282,3 +282,8 @@ def _get_data_scale(X, Y, Z):
|
|
|
282
282
|
ptp_y = Y.max() - Y.min()
|
|
283
283
|
ptp_z = Z.max() - Z.min()
|
|
284
284
|
return np.sqrt(ptp_x**2 + ptp_y**2 + ptp_z**2)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _heuristic_show():
|
|
288
|
+
"""Try guessing whether plt.show() should be called automatically."""
|
|
289
|
+
return False
|
iplotx/version.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iplotx
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.7.0
|
|
4
|
+
Summary: Universal network and tree visualisation library.
|
|
5
5
|
Project-URL: Homepage, https://github.com/fabilab/iplotx
|
|
6
6
|
Project-URL: Documentation, https://readthedocs.org/iplotx
|
|
7
7
|
Project-URL: Repository, https://github.com/fabilab/iplotx.git
|
|
@@ -41,7 +41,7 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
[](https://iplotx.readthedocs.io/en/latest/)
|
|
42
42
|
[](https://coveralls.io/github/fabilab/iplotx?branch=main)
|
|
43
43
|

|
|
44
|
-
[
|
|
44
|
+
[DOI](https://f1000research.com/articles/14-1377)
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
# iplotx
|
|
@@ -90,10 +90,10 @@ See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documen
|
|
|
90
90
|
See [gallery](https://iplotx.readthedocs.io/en/latest/gallery/index.html).
|
|
91
91
|
|
|
92
92
|
## Citation
|
|
93
|
-
If you use `iplotx` for publication figures, please cite
|
|
93
|
+
If you use `iplotx` for publication figures, please cite:
|
|
94
94
|
|
|
95
95
|
```
|
|
96
|
-
F. Zanini.
|
|
96
|
+
F. Zanini. A universal tool for visualisation of networks and trees in Python. F1000Research 2025, 14:1377. https://doi.org/10.12688/f1000research.173131.1
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
## Features
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
iplotx/__init__.py,sha256=RKlRSSEAv2qECd6rCiovdLDu-4k1eXMGCOCPt0xwpFA,523
|
|
2
2
|
iplotx/artists.py,sha256=2dBDT240zGwKb6tIc_y9pXeyU3LuYeF9wjj2tvi4KJo,730
|
|
3
3
|
iplotx/label.py,sha256=7eS8ByadrhdIFOZz19U4VrS-oXY_ndFYNB-D4RZbFqI,9573
|
|
4
|
-
iplotx/plotting.py,sha256=
|
|
4
|
+
iplotx/plotting.py,sha256=QlXCh3t1J9YmzkqrS6ozwSilFxZ1hwBHHWW-kpd-7zM,17679
|
|
5
5
|
iplotx/typing.py,sha256=QLdzV358IiD1CFe88MVp0D77FSx5sSAVUmM_2WPPE8I,1463
|
|
6
|
-
iplotx/version.py,sha256=
|
|
6
|
+
iplotx/version.py,sha256=7dTkHVHx2G_FnFiWdcEX1gkeNeCO9nu53SE10IwwwKM,66
|
|
7
7
|
iplotx/vertex.py,sha256=Ta48M_6ZT8xKQWdI5XHiRxTt2LlJ9vshiDk34OzKYlY,16585
|
|
8
8
|
iplotx/art3d/vertex.py,sha256=Xf8Um30X2doCd8KdNN7332F6BxC4k72Mb_GeRAuzQfQ,2545
|
|
9
9
|
iplotx/art3d/edge/__init__.py,sha256=uw1U_mMXqcZAvea-7JbU1PUKULQD1CMMrbwY02tiWRQ,8529
|
|
10
10
|
iplotx/art3d/edge/arrow.py,sha256=14BFXY9kDOUGPZl2fMD9gRVGyaaN5kyd-l6ikBg6WHU,3601
|
|
11
11
|
iplotx/art3d/edge/geometry.py,sha256=76VUmpPG-4Mls7x_994dMwdDPrWWnjT7nHJsHfwK_hA,2467
|
|
12
|
-
iplotx/edge/__init__.py,sha256=
|
|
12
|
+
iplotx/edge/__init__.py,sha256=mp_JRGeJWPXZNpQ6vTgTdzgVO1YxcZMKuVKarJGuLnY,27522
|
|
13
13
|
iplotx/edge/arrow.py,sha256=ymup2YT_0GVYMtZw_DSKrZqFHG_ysYteEhmoL6T8Mu4,17563
|
|
14
|
-
iplotx/edge/geometry.py,sha256=
|
|
14
|
+
iplotx/edge/geometry.py,sha256=Qyi7Q7sOGAFXU6gFeWFLm6OoGetEasrfv8HzgSWO2gY,20210
|
|
15
15
|
iplotx/edge/leaf.py,sha256=SyGMv2PIOoH0pey8-aMVaZheK3hNe1Qz_okcyWbc4E4,4268
|
|
16
16
|
iplotx/edge/ports.py,sha256=BpkbiEhX4mPBBAhOv4jcKFG4Y8hxXz5GRtVLCC0jbtI,1235
|
|
17
17
|
iplotx/ingest/__init__.py,sha256=k1Q-7lSdotMR4RkF1x0t19RFsTknohX0L507Dw69WyU,5035
|
|
@@ -41,8 +41,8 @@ iplotx/tree/cascades.py,sha256=Wwqhy46QGeb4LNGUuz_-bgNWUMz6PFzs_dIxIb1dtqc,8394
|
|
|
41
41
|
iplotx/tree/scalebar.py,sha256=Yxt_kF8JdTwKGa8Jzqt3qVePPK5ZBG8P0EiONrsh3E8,11863
|
|
42
42
|
iplotx/utils/geometry.py,sha256=6RrC6qaB0-1vIk1LhGA4CfsiMd-9JNniSPyL_l9mshE,9245
|
|
43
43
|
iplotx/utils/internal.py,sha256=WWfcZDGK8Ut1y_tOHRGg9wSqY1bwSeLQO7dHM_8Tvwo,107
|
|
44
|
-
iplotx/utils/matplotlib.py,sha256=
|
|
44
|
+
iplotx/utils/matplotlib.py,sha256=T-jiqy8KxF1Q4BofT1rZbbdtmSC-j_kjNRcOg_IZpYM,8720
|
|
45
45
|
iplotx/utils/style.py,sha256=vyNP80nDYVinqm6_9ltCJCtjK35ZcGlHvOskNv3eQBc,4225
|
|
46
|
-
iplotx-1.
|
|
47
|
-
iplotx-1.
|
|
48
|
-
iplotx-1.
|
|
46
|
+
iplotx-1.7.0.dist-info/METADATA,sha256=gItmBkiLmtBY73aY3IIycXX61yghAdv0wBmMXsDBpSw,5333
|
|
47
|
+
iplotx-1.7.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
48
|
+
iplotx-1.7.0.dist-info/RECORD,,
|