iplotx 0.12.0__py3-none-any.whl → 1.0.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/artists.py CHANGED
@@ -3,19 +3,21 @@ All artists defined in iplotx.
3
3
  """
4
4
 
5
5
  from .network import NetworkArtist
6
- from .tree import TreeArtist
6
+ from .network.groups import GroupingCollection
7
7
  from .vertex import VertexCollection
8
8
  from .edge import EdgeCollection
9
9
  from .label import LabelCollection
10
10
  from .edge.arrow import EdgeArrowCollection
11
11
  from .edge.leaf import LeafEdgeCollection
12
- from .cascades import CascadeCollection
13
12
  from .art3d.vertex import Vertex3DCollection
14
13
  from .art3d.edge import Edge3DCollection
14
+ from .tree import TreeArtist
15
+ from .tree.cascades import CascadeCollection
15
16
 
16
17
 
17
18
  ___all__ = (
18
19
  NetworkArtist,
20
+ GroupingCollection,
19
21
  TreeArtist,
20
22
  VertexCollection,
21
23
  EdgeCollection,
@@ -7,33 +7,33 @@ import numpy as np
7
7
  import pandas as pd
8
8
  import matplotlib as mpl
9
9
 
10
- from .typing import (
10
+ from ..typing import (
11
11
  GraphType,
12
12
  LayoutType,
13
13
  )
14
- from .style import (
14
+ from ..style import (
15
15
  get_style,
16
16
  rotate_style,
17
17
  )
18
- from .utils.matplotlib import (
18
+ from ..utils.matplotlib import (
19
19
  _stale_wrapper,
20
20
  _forwarder,
21
21
  _build_cmap_fun,
22
22
  )
23
- from .ingest import (
23
+ from ..ingest import (
24
24
  ingest_network_data,
25
25
  )
26
- from .vertex import (
26
+ from ..vertex import (
27
27
  VertexCollection,
28
28
  )
29
- from .edge import (
29
+ from ..edge import (
30
30
  EdgeCollection,
31
31
  make_stub_patch as make_undirected_edge_patch,
32
32
  )
33
- from .art3d.vertex import (
33
+ from ..art3d.vertex import (
34
34
  vertex_collection_2d_to_3d,
35
35
  )
36
- from .art3d.edge import (
36
+ from ..art3d.edge import (
37
37
  Edge3DCollection,
38
38
  edge_collection_2d_to_3d,
39
39
  )
@@ -1,5 +1,5 @@
1
1
  """
2
- Module for vertex groupings code, especially the GroupingArtist class.
2
+ Module for vertex groupings code, especially the GroupingCollection class.
3
3
  """
4
4
 
5
5
  from typing import Union
@@ -9,22 +9,22 @@ import matplotlib as mpl
9
9
  from matplotlib.collections import PatchCollection
10
10
 
11
11
 
12
- from .typing import (
12
+ from ..typing import (
13
13
  GroupingType,
14
14
  LayoutType,
15
15
  )
16
- from .ingest.heuristics import (
16
+ from ..ingest.heuristics import (
17
17
  normalise_layout,
18
18
  normalise_grouping,
19
19
  )
20
- from .style import get_style, rotate_style
21
- from .utils.geometry import (
20
+ from ..style import get_style, rotate_style
21
+ from ..utils.geometry import (
22
22
  convex_hull,
23
23
  _compute_group_path_with_vertex_padding,
24
24
  )
25
25
 
26
26
 
27
- class GroupingArtist(PatchCollection):
27
+ class GroupingCollection(PatchCollection):
28
28
  """Matplotlib artist for a vertex grouping (clustering/cover).
29
29
 
30
30
  This class is used to plot patches surrounding groups of vertices in a network.
iplotx/plotting.py CHANGED
@@ -13,7 +13,7 @@ from .typing import (
13
13
  TreeType,
14
14
  )
15
15
  from .network import NetworkArtist
16
- from .groups import GroupingArtist
16
+ from .network.groups import GroupingCollection
17
17
  from .tree import TreeArtist
18
18
  from .style import context
19
19
 
@@ -101,7 +101,7 @@ def network(
101
101
  nwkart = None
102
102
 
103
103
  if grouping is not None:
104
- grpart = GroupingArtist(
104
+ grpart = GroupingCollection(
105
105
  grouping,
106
106
  layout,
107
107
  network=network,
@@ -10,38 +10,41 @@ import numpy as np
10
10
  import pandas as pd
11
11
  import matplotlib as mpl
12
12
 
13
- from .style import (
13
+ from ..style import (
14
14
  context,
15
15
  get_style,
16
16
  rotate_style,
17
17
  merge_styles,
18
18
  )
19
- from .utils.matplotlib import (
19
+ from ..utils.matplotlib import (
20
20
  _stale_wrapper,
21
21
  _forwarder,
22
22
  _build_cmap_fun,
23
23
  )
24
- from .ingest import (
24
+ from ..ingest import (
25
25
  ingest_tree_data,
26
26
  data_providers,
27
27
  )
28
- from .vertex import (
28
+ from ..vertex import (
29
29
  VertexCollection,
30
30
  )
31
- from .edge import (
31
+ from ..edge import (
32
32
  EdgeCollection,
33
33
  make_stub_patch as make_undirected_edge_patch,
34
34
  )
35
- from .edge.leaf import (
35
+ from ..edge.leaf import (
36
36
  LeafEdgeCollection,
37
37
  )
38
- from .label import (
38
+ from ..label import (
39
39
  LabelCollection,
40
40
  )
41
41
  from .cascades import (
42
42
  CascadeCollection,
43
43
  )
44
- from .network import (
44
+ from .scalebar import (
45
+ TreeScalebarArtist,
46
+ )
47
+ from ..network import (
45
48
  _update_from_internal,
46
49
  )
47
50
 
@@ -663,6 +666,40 @@ class TreeArtist(mpl.artist.Artist):
663
666
  """Get the orientation of the tree layout."""
664
667
  return self._ipx_internal_data.get("orientation", None)
665
668
 
669
+ def scalebar(
670
+ self,
671
+ loc: str = "upper left",
672
+ **kwargs,
673
+ ):
674
+ """Create scalebar for the tree.
675
+
676
+ Parameters:
677
+ legth: Length of the scalebar in data units.
678
+ loc: Location of the scalebar. Same options as `matplotlib.legend`.
679
+ kwargs: Additional keyword arguments passed to `TreeScalebarArtist`. These are
680
+ generally the same options that you would pass to a legend, such as
681
+ bbox_to_anchor, bbox_transform, etc.
682
+ Returns:
683
+ The artist with the tree scale bar.
684
+ """
685
+ if self.axes is None:
686
+ raise RuntimeError("Cannot add a scalebar if the artist is not in an Axes.")
687
+
688
+ scalebar = TreeScalebarArtist(
689
+ self,
690
+ layout=self.get_layout_name(),
691
+ loc=loc,
692
+ )
693
+
694
+ # Remove previous scalebars if any
695
+ for art in self.axes._children:
696
+ if isinstance(art, TreeScalebarArtist) and art._treeartist == self:
697
+ art.remove()
698
+
699
+ self.axes.add_artist(scalebar)
700
+
701
+ return scalebar
702
+
666
703
  def style_subtree(
667
704
  self,
668
705
  nodes: Sequence[Hashable],
@@ -5,16 +5,15 @@ from typing import (
5
5
  import warnings
6
6
  import numpy as np
7
7
  import pandas as pd
8
+ import matplotlib as mpl
8
9
 
9
- from .typing import (
10
+ from ..typing import (
10
11
  TreeType,
11
12
  )
12
- from .ingest.typing import (
13
+ from ..ingest.typing import (
13
14
  TreeDataProvider,
14
15
  )
15
- import matplotlib as mpl
16
-
17
- from .style import (
16
+ from ..style import (
18
17
  copy_with_deep_values,
19
18
  rotate_style,
20
19
  )
@@ -0,0 +1,326 @@
1
+ from typing import (
2
+ Any,
3
+ )
4
+ import numpy as np
5
+ from matplotlib import (
6
+ _api,
7
+ )
8
+ from matplotlib import collections as mcoll
9
+ from matplotlib.legend import Legend
10
+ from matplotlib.legend_handler import HandlerErrorbar
11
+ from matplotlib.lines import Line2D
12
+ from matplotlib.offsetbox import (
13
+ HPacker,
14
+ VPacker,
15
+ DrawingArea,
16
+ TextArea,
17
+ )
18
+
19
+
20
+ def _update_prop(legend_artist, orig_handle):
21
+ # NOTE: This is de facto a bug in mpl, because Line2D.set_linestyle()
22
+ # does two things: it reformats tuple-style dashing, and it sets the
23
+ # artist as stale. We want to do the former only here, so we reset
24
+ # the artist as the original stale state after calling it.
25
+ stale_orig = legend_artist.stale
26
+ legend_artist.set_linestyle(orig_handle.get_linestyle()[0])
27
+ legend_artist.stale = stale_orig
28
+
29
+ # These other properties can be set directly.
30
+ legend_artist._linewidth = orig_handle.get_linewidth()[0]
31
+ legend_artist._color = orig_handle.get_edgecolor()[0]
32
+ legend_artist._gapcolor = orig_handle._gapcolor
33
+
34
+
35
+ class TreeScalebarArtist(Legend):
36
+ def __init__(
37
+ self,
38
+ treeartist,
39
+ layout: str = "horizontal",
40
+ frameon=False,
41
+ **kwargs,
42
+ ):
43
+ handles = [treeartist.get_edges()]
44
+ labels = [""]
45
+ self._layout = layout
46
+ self._treeartist = treeartist
47
+
48
+ if layout == "vertical":
49
+ handler_kwargs = dict(xerr_size=0, yerr_size=1)
50
+ else:
51
+ handler_kwargs = dict(xerr_size=1)
52
+ handler = TreeLegendHandler(
53
+ update_func=_update_prop,
54
+ **handler_kwargs,
55
+ )
56
+
57
+ super().__init__(
58
+ treeartist.axes,
59
+ handles,
60
+ labels,
61
+ handler_map={handles[0]: handler},
62
+ frameon=frameon,
63
+ **kwargs,
64
+ )
65
+
66
+ def _init_legend_box(self, handles, labels, markerfirst=True):
67
+ """
68
+ Create the legend box.
69
+
70
+ This is a modified version of the original Legend._init_legend_box
71
+ method to accommodate a scale bar.
72
+ """
73
+
74
+ fontsize = self._fontsize
75
+
76
+ # legend_box is a HPacker, horizontally packed with columns.
77
+ # Each column is a VPacker, vertically packed with legend items.
78
+ # Each legend item is a HPacker packed with:
79
+ # - handlebox: a DrawingArea which contains the legend handle.
80
+ # - labelbox: a TextArea which contains the legend text.
81
+
82
+ text_list = [] # the list of text instances
83
+ handle_list = [] # the list of handle instances
84
+ handles_and_labels = []
85
+
86
+ # The approximate height and descent of text. These values are
87
+ # only used for plotting the legend handle.
88
+ descent = 0.35 * fontsize * (self.handleheight - 0.7) # heuristic.
89
+ height = fontsize * self.handleheight - descent
90
+ # each handle needs to be drawn inside a box of (x, y, w, h) =
91
+ # (0, -descent, width, height). And their coordinates should
92
+ # be given in the display coordinates.
93
+
94
+ # The transformation of each handle will be automatically set
95
+ # to self.get_transform(). If the artist does not use its
96
+ # default transform (e.g., Collections), you need to
97
+ # manually set their transform to the self.get_transform().
98
+ legend_handler_map = self.get_legend_handler_map()
99
+
100
+ for orig_handle, label in zip(handles, labels):
101
+ handler = self.get_legend_handler(legend_handler_map, orig_handle)
102
+ if handler is None:
103
+ _api.warn_external(
104
+ "Legend does not support handles for "
105
+ f"{type(orig_handle).__name__} "
106
+ "instances.\nA proxy artist may be used "
107
+ "instead.\nSee: https://matplotlib.org/"
108
+ "stable/users/explain/axes/legend_guide.html"
109
+ "#controlling-the-legend-entries"
110
+ )
111
+ # No handle for this artist, so we just defer to None.
112
+ handle_list.append(None)
113
+ else:
114
+ handlebox = DrawingArea(
115
+ width=self.handlelength * fontsize,
116
+ height=height,
117
+ xdescent=0.0,
118
+ ydescent=descent,
119
+ )
120
+ # Create the artist for the legend which represents the
121
+ # original artist/handle.
122
+ handle_list.append(handler.legend_artist(self, orig_handle, fontsize, handlebox))
123
+
124
+ # The scale bar line is in this handle
125
+ bar_handle = handle_list[-1]
126
+ label = self._get_label_from_bar_handle(bar_handle)
127
+
128
+ textbox = TextArea(
129
+ label,
130
+ multilinebaseline=True,
131
+ textprops=dict(
132
+ verticalalignment="baseline",
133
+ horizontalalignment="left",
134
+ fontproperties=self.prop,
135
+ ),
136
+ )
137
+ text_list.append(textbox._text)
138
+
139
+ handles_and_labels.append((handlebox, textbox))
140
+
141
+ columnbox = []
142
+ # array_split splits n handles_and_labels into ncols columns, with the
143
+ # first n%ncols columns having an extra entry. filter(len, ...)
144
+ # handles the case where n < ncols: the last ncols-n columns are empty
145
+ # and get filtered out.
146
+ for handles_and_labels_column in filter(
147
+ len, np.array_split(handles_and_labels, self._ncols)
148
+ ):
149
+ # pack handlebox and labelbox into itembox
150
+ if self._layout == "vertical":
151
+ itempacker = HPacker
152
+ else:
153
+ itempacker = VPacker
154
+ itemboxes = [
155
+ itempacker(
156
+ pad=0,
157
+ sep=self.handletextpad * fontsize,
158
+ children=[h, t] if markerfirst else [t, h],
159
+ align="center",
160
+ )
161
+ for h, t in handles_and_labels_column
162
+ ]
163
+ # pack columnbox
164
+ alignment = "baseline" if markerfirst else "right"
165
+ columnbox.append(
166
+ VPacker(
167
+ pad=0, sep=self.labelspacing * fontsize, align=alignment, children=itemboxes
168
+ )
169
+ )
170
+
171
+ mode = "expand" if self._mode == "expand" else "fixed"
172
+ sep = self.columnspacing * fontsize
173
+ self._legend_handle_box = HPacker(
174
+ pad=0, sep=sep, align="baseline", mode=mode, children=columnbox
175
+ )
176
+ self._legend_title_box = TextArea("")
177
+ self._legend_box = VPacker(
178
+ pad=self.borderpad * fontsize,
179
+ sep=self.labelspacing * fontsize,
180
+ align=self._alignment,
181
+ children=[self._legend_title_box, self._legend_handle_box],
182
+ )
183
+ self._legend_box.set_figure(self.get_figure(root=False))
184
+ self._legend_box.axes = self.axes
185
+ self.texts = text_list
186
+ self.legend_handles = handle_list
187
+
188
+ def _get_label_from_bar_handle(self, bar_handle: Any) -> str:
189
+ # Extract the x coordinates of the scale bar
190
+ p0, p1 = bar_handle.get_segments()[0]
191
+
192
+ bar_trans = bar_handle.get_transform()
193
+ data_trans = self.parent.transData
194
+ # FIXME: this is off, probably because of some Packer anchor additional transform
195
+ composite_trans = data_trans.inverted() + bar_trans
196
+
197
+ p0_data = composite_trans.transform(p0)
198
+ p1_data = composite_trans.transform(p1)
199
+ distance = np.linalg.norm(p1_data - p0_data)
200
+ label = f"{distance:.2f}"
201
+ return label
202
+
203
+ def draw(self, renderer):
204
+ bar_handle = self.legend_handles[0]
205
+ label = self._get_label_from_bar_handle(bar_handle)
206
+
207
+ text_handle = (
208
+ self._legend_box.get_children()[1].get_children()[0].get_children()[0].get_children()[1]
209
+ )
210
+ # Bypass stale=True (we are already redrawing)
211
+ text_handle.set_text(label)
212
+
213
+ super().draw(renderer)
214
+
215
+
216
+ class TreeLegendHandler(HandlerErrorbar):
217
+ def __init__(self, marker_size=6, **kw):
218
+ self.marker_size = marker_size
219
+ super().__init__(**kw)
220
+
221
+ def create_artists(
222
+ self,
223
+ legend,
224
+ orig_handle,
225
+ xdescent,
226
+ ydescent,
227
+ width,
228
+ height,
229
+ fontsize,
230
+ trans,
231
+ ):
232
+ # docstring inherited
233
+ plotline = orig_handle
234
+
235
+ xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent, width, height, fontsize)
236
+ ydata = np.full_like(xdata, (height - ydescent) / 2)
237
+
238
+ xdata_marker = np.asarray(xdata_marker)
239
+ ydata_marker = np.asarray(ydata[: len(xdata_marker)])
240
+
241
+ xerr_size, yerr_size = self.get_err_size(
242
+ legend, xdescent, ydescent, width, height, fontsize
243
+ )
244
+
245
+ if legend._layout == "vertical":
246
+ xdata, ydata = np.array(
247
+ [
248
+ ((x, y - yerr_size), (x, y + yerr_size))
249
+ for x, y in zip(xdata_marker, ydata_marker)
250
+ ]
251
+ ).T
252
+
253
+ legline = Line2D(xdata, ydata)
254
+
255
+ legline_marker = Line2D(xdata_marker, ydata_marker)
256
+
257
+ # when plotlines are None (only errorbars are drawn), we just
258
+ # make legline invisible.
259
+ if plotline is None:
260
+ legline.set_visible(False)
261
+ legline_marker.set_visible(False)
262
+ else:
263
+ self.update_prop(legline, plotline, legend)
264
+
265
+ legline.set_drawstyle("default")
266
+ legline.set_marker("none")
267
+
268
+ self.update_prop(legline_marker, plotline, legend)
269
+ legline_marker.set_linestyle("None")
270
+
271
+ if legend.markerscale != 1:
272
+ newsz = legline_marker.get_markersize() * legend.markerscale
273
+ legline_marker.set_markersize(newsz)
274
+
275
+ handle_barlinecols = []
276
+ handle_caplines = []
277
+
278
+ if legend._layout != "vertical":
279
+ verts = [
280
+ ((x - xerr_size, y), (x + xerr_size, y)) for x, y in zip(xdata_marker, ydata_marker)
281
+ ]
282
+ coll = mcoll.LineCollection(verts)
283
+ self.update_prop(coll, plotline, legend)
284
+ handle_barlinecols.append(coll)
285
+
286
+ # Always show the cap lines
287
+ if True:
288
+ capline_left = Line2D(xdata_marker - xerr_size, ydata_marker)
289
+ capline_right = Line2D(xdata_marker + xerr_size, ydata_marker)
290
+ self.update_prop(capline_left, plotline, legend)
291
+ self.update_prop(capline_right, plotline, legend)
292
+ capline_left.set_marker("|")
293
+ capline_right.set_marker("|")
294
+
295
+ handle_caplines.append(capline_left)
296
+ handle_caplines.append(capline_right)
297
+
298
+ else:
299
+ verts = [
300
+ ((x, y - yerr_size), (x, y + yerr_size)) for x, y in zip(xdata_marker, ydata_marker)
301
+ ]
302
+ coll = mcoll.LineCollection(verts)
303
+ self.update_prop(coll, plotline, legend)
304
+ handle_barlinecols.append(coll)
305
+
306
+ # Always show the cap lines
307
+ if True:
308
+ capline_left = Line2D(xdata_marker, ydata_marker - yerr_size)
309
+ capline_right = Line2D(xdata_marker, ydata_marker + yerr_size)
310
+ self.update_prop(capline_left, plotline, legend)
311
+ self.update_prop(capline_right, plotline, legend)
312
+ capline_left.set_marker("_")
313
+ capline_right.set_marker("_")
314
+
315
+ handle_caplines.append(capline_left)
316
+ handle_caplines.append(capline_right)
317
+
318
+ artists = [
319
+ *handle_barlinecols,
320
+ *handle_caplines,
321
+ legline,
322
+ legline_marker,
323
+ ]
324
+ for artist in artists:
325
+ artist.set_transform(trans)
326
+ return artists
iplotx/version.py CHANGED
@@ -2,4 +2,4 @@
2
2
  iplotx version information module.
3
3
  """
4
4
 
5
- __version__ = "0.12.0"
5
+ __version__ = "1.0.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iplotx
3
- Version: 0.12.0
3
+ Version: 1.0.0
4
4
  Summary: Plot networkx from igraph and networkx.
5
5
  Project-URL: Homepage, https://github.com/fabilab/iplotx
6
6
  Project-URL: Documentation, https://readthedocs.org/iplotx
@@ -1,14 +1,10 @@
1
1
  iplotx/__init__.py,sha256=RzSct91jO8abrxOIn33rKEnDUgYpu1oj4olbObgX_hs,489
2
- iplotx/artists.py,sha256=XNtRwuvQdKkZCAejILydLD3J5B87sg5xPXuZFv_Gkk8,654
3
- iplotx/cascades.py,sha256=OPqF7Huls-HFmDA5MCF6DEZlUeRVaXsbQcHBoKAgNJs,8182
4
- iplotx/groups.py,sha256=g6ahm61BSBmd2weIjr40MvPi_GcNRgvNb9YklQsiza4,6784
2
+ iplotx/artists.py,sha256=2dBDT240zGwKb6tIc_y9pXeyU3LuYeF9wjj2tvi4KJo,730
5
3
  iplotx/label.py,sha256=7eS8ByadrhdIFOZz19U4VrS-oXY_ndFYNB-D4RZbFqI,9573
6
4
  iplotx/layout.py,sha256=KxmRLqjo8AYCBAmXez8rIiLU2sM34qhb6ox9AHYwRyE,4839
7
- iplotx/network.py,sha256=mhR1hwlLrATYJfCZUgk7sfmtw3yEjAE0TtE0b-1N8hE,13567
8
- iplotx/plotting.py,sha256=icEefWJnS2lEGLp4t1LhDSP40JuvNKgOie3FDLOnTMk,13195
9
- iplotx/tree.py,sha256=TxbNoBHS0CfswrcMIWCNtnOl_3e4-PwCrVo0goywC0U,28807
5
+ iplotx/plotting.py,sha256=FvV33DCuEjJwO9ytiYJuQmfOywgF-cDANd6nEE5s8R0,13211
10
6
  iplotx/typing.py,sha256=QLdzV358IiD1CFe88MVp0D77FSx5sSAVUmM_2WPPE8I,1463
11
- iplotx/version.py,sha256=OAoDyBg_N0NwrLolwb2vnkue-AwN9sTDzRmDcTNfAog,67
7
+ iplotx/version.py,sha256=Zw6LAvjlzbItG1QBPJb1Tuqkb2PVUYsDwCVRYEJusgc,66
12
8
  iplotx/vertex.py,sha256=_yYyvusn4vYvi6RBEW6CHa3vnbv43GnZylnMIaK4bG0,16040
13
9
  iplotx/art3d/vertex.py,sha256=Xf8Um30X2doCd8KdNN7332F6BxC4k72Mb_GeRAuzQfQ,2545
14
10
  iplotx/art3d/edge/__init__.py,sha256=uw1U_mMXqcZAvea-7JbU1PUKULQD1CMMrbwY02tiWRQ,8529
@@ -31,13 +27,18 @@ iplotx/ingest/providers/tree/dendropy.py,sha256=uRMe46PfDPUTeNInUO2Gbp4pVr-WIFIZ
31
27
  iplotx/ingest/providers/tree/ete4.py,sha256=D7usSq0MOjzrk3EoLi834IlaDGwv7_qG6Qt0ptfKqfI,928
32
28
  iplotx/ingest/providers/tree/simple.py,sha256=aV9wGqBomJ5klM_aJQeuL_Q_J1pLCv6AFN98BPDiKUw,2593
33
29
  iplotx/ingest/providers/tree/skbio.py,sha256=O1KUr8tYi28pZ3VVjapgO4Uj-YpMuix3GhOH5je8Lv4,822
30
+ iplotx/network/__init__.py,sha256=oEv6f8oFYrtcI_NKabr8a_oIWTc1jXXTl_yO1xox_rE,13575
31
+ iplotx/network/groups.py,sha256=E_eYVXRHjv1DcyA4RupTkMa-rRFrIKkt9Rxn_Elw9Nc,6796
34
32
  iplotx/style/__init__.py,sha256=rf1GutrE8hHUhCoe4FGKYX-aNtHuu_U-kYQnqUxZNrY,10282
35
33
  iplotx/style/leaf_info.py,sha256=3xBn7xv9Uy2KAqdhM9S6ew5ZBJrGRTXRL3xXb8atfLw,1018
36
34
  iplotx/style/library.py,sha256=58Y8BlllGLsR4pQM7_PVCP5tH6_4GkchXZvJpqGHlcg,8534
35
+ iplotx/tree/__init__.py,sha256=6a8cbTd-OS-x8GEZJeRo3vneVjI98AiQW_gIo1H7h3Y,29969
36
+ iplotx/tree/cascades.py,sha256=on5GyqbWasl1zgK7bYXYQE0LOSfHc1z-1hnm0GWd6aw,8184
37
+ iplotx/tree/scalebar.py,sha256=QC2l-Nx39g8fkO1tHHvbrtzLncfQc9L57BQniSk2h5Q,11849
37
38
  iplotx/utils/geometry.py,sha256=6RrC6qaB0-1vIk1LhGA4CfsiMd-9JNniSPyL_l9mshE,9245
38
39
  iplotx/utils/internal.py,sha256=WWfcZDGK8Ut1y_tOHRGg9wSqY1bwSeLQO7dHM_8Tvwo,107
39
40
  iplotx/utils/matplotlib.py,sha256=p_53Oamof0RI4mtV8HrdDtZbgVqUxeUZ_KDvLZSiBUQ,8604
40
41
  iplotx/utils/style.py,sha256=vyNP80nDYVinqm6_9ltCJCtjK35ZcGlHvOskNv3eQBc,4225
41
- iplotx-0.12.0.dist-info/METADATA,sha256=OcfxvA_JL2GOXYH7_67iDL1N4_U3fDm7--3nXbUHKU8,5087
42
- iplotx-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
- iplotx-0.12.0.dist-info/RECORD,,
42
+ iplotx-1.0.0.dist-info/METADATA,sha256=VsUs2_FiPrGNcfAfnL-T0fB9RObJCdAUvjaEUO46vFg,5086
43
+ iplotx-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ iplotx-1.0.0.dist-info/RECORD,,