marsilea 0.3.2__py3-none-any.whl → 0.3.3__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.
- marsilea/__init__.py +3 -2
- marsilea/_api.py +3 -2
- marsilea/_deform.py +44 -38
- marsilea/base.py +702 -118
- marsilea/dataset.py +49 -23
- marsilea/dendrogram.py +119 -84
- marsilea/exceptions.py +5 -6
- marsilea/heatmap.py +85 -25
- marsilea/layers.py +77 -69
- marsilea/layout.py +132 -102
- marsilea/plotter/__init__.py +29 -0
- marsilea/plotter/_images.py +37 -7
- marsilea/plotter/_seaborn.py +35 -24
- marsilea/plotter/_utils.py +3 -2
- marsilea/plotter/arc.py +29 -19
- marsilea/plotter/area.py +80 -0
- marsilea/plotter/bar.py +113 -90
- marsilea/plotter/base.py +76 -49
- marsilea/plotter/bio.py +40 -30
- marsilea/plotter/mesh.py +184 -88
- marsilea/plotter/text.py +303 -194
- marsilea/upset.py +229 -151
- marsilea/utils.py +23 -10
- {marsilea-0.3.2.dist-info → marsilea-0.3.3.dist-info}/LICENSE +1 -1
- marsilea-0.3.3.dist-info/METADATA +74 -0
- marsilea-0.3.3.dist-info/RECORD +27 -0
- marsilea-0.3.2.dist-info/METADATA +0 -50
- marsilea-0.3.2.dist-info/RECORD +0 -26
- {marsilea-0.3.2.dist-info → marsilea-0.3.3.dist-info}/WHEEL +0 -0
marsilea/layers.py
CHANGED
|
@@ -22,8 +22,8 @@ class LayersMesh(RenderPlan):
|
|
|
22
22
|
It offers two flexible ways to specify layers:
|
|
23
23
|
|
|
24
24
|
#. A single layer of data containing different elements.
|
|
25
|
-
#. Multiple layers of data, where each layer represents a customized element,
|
|
26
|
-
overlaying elements on top of one another
|
|
25
|
+
#. Multiple layers of data, where each layer represents a customized element, \
|
|
26
|
+
overlaying elements on top of one another.
|
|
27
27
|
|
|
28
28
|
When supplying multiple layers,
|
|
29
29
|
the drawing order follows the order of the input array.
|
|
@@ -48,6 +48,7 @@ class LayersMesh(RenderPlan):
|
|
|
48
48
|
props : dict
|
|
49
49
|
See :class:`matplotlib.text.Text`
|
|
50
50
|
|
|
51
|
+
|
|
51
52
|
Examples
|
|
52
53
|
--------
|
|
53
54
|
|
|
@@ -78,23 +79,27 @@ class LayersMesh(RenderPlan):
|
|
|
78
79
|
>>> _, ax = plt.subplots()
|
|
79
80
|
>>> LayersMesh(layers=[d1, d2, d3], pieces=pieces).render(ax)
|
|
80
81
|
|
|
82
|
+
|
|
81
83
|
"""
|
|
84
|
+
|
|
82
85
|
render_main = True
|
|
83
86
|
|
|
84
|
-
def __init__(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
data=None,
|
|
90
|
+
layers=None,
|
|
91
|
+
pieces=None,
|
|
92
|
+
shrink=(1.0, 1.0),
|
|
93
|
+
label=None,
|
|
94
|
+
label_loc=None,
|
|
95
|
+
props=None,
|
|
96
|
+
legend_kws=None,
|
|
97
|
+
):
|
|
92
98
|
# render one layer
|
|
93
99
|
# with different elements
|
|
94
100
|
if data is not None:
|
|
95
101
|
if not isinstance(pieces, Mapping):
|
|
96
|
-
msg = f"Expect pieces to be dict "
|
|
97
|
-
f"but found {type(pieces)} instead."
|
|
102
|
+
msg = f"Expect pieces to be dict " f"but found {type(pieces)} instead."
|
|
98
103
|
raise TypeError(msg)
|
|
99
104
|
self.pieces_mapper = pieces
|
|
100
105
|
self.mode = "cell"
|
|
@@ -104,8 +109,7 @@ class LayersMesh(RenderPlan):
|
|
|
104
109
|
# each layer is an elements
|
|
105
110
|
else:
|
|
106
111
|
if not isinstance(pieces, Iterable):
|
|
107
|
-
msg = f"Expect pieces to be list "
|
|
108
|
-
f"but found {type(pieces)} instead."
|
|
112
|
+
msg = f"Expect pieces to be list " f"but found {type(pieces)} instead."
|
|
109
113
|
raise TypeError(msg)
|
|
110
114
|
self.pieces, data = self._sort_by_zorder(pieces, layers)
|
|
111
115
|
self.mode = "layer"
|
|
@@ -118,8 +122,7 @@ class LayersMesh(RenderPlan):
|
|
|
118
122
|
self.label = label
|
|
119
123
|
self.label_loc = label_loc
|
|
120
124
|
self.props = props
|
|
121
|
-
default_legend_kws = dict(frameon=False, handlelength=1,
|
|
122
|
-
handleheight=1)
|
|
125
|
+
default_legend_kws = dict(frameon=False, handlelength=1, handleheight=1)
|
|
123
126
|
if legend_kws is not None:
|
|
124
127
|
default_legend_kws.update(legend_kws)
|
|
125
128
|
self._legend_kws = default_legend_kws
|
|
@@ -129,7 +132,7 @@ class LayersMesh(RenderPlan):
|
|
|
129
132
|
ix_pieces = sorted(enumerate(pieces), key=lambda x: x[1].zorder)
|
|
130
133
|
sorted_pieces = []
|
|
131
134
|
sorted_layers = []
|
|
132
|
-
for
|
|
135
|
+
for ix, piece in ix_pieces:
|
|
133
136
|
sorted_pieces.append(piece)
|
|
134
137
|
sorted_layers.append(layers[ix])
|
|
135
138
|
return sorted_pieces, sorted_layers
|
|
@@ -147,8 +150,12 @@ class LayersMesh(RenderPlan):
|
|
|
147
150
|
new_handles.append(h)
|
|
148
151
|
labels.append(h.get_label())
|
|
149
152
|
handler_map[h] = h
|
|
150
|
-
return ListLegend(
|
|
151
|
-
|
|
153
|
+
return ListLegend(
|
|
154
|
+
handles=new_handles,
|
|
155
|
+
labels=labels,
|
|
156
|
+
handler_map=handler_map,
|
|
157
|
+
**self._legend_kws,
|
|
158
|
+
)
|
|
152
159
|
|
|
153
160
|
def render_ax(self, spec):
|
|
154
161
|
ax = spec.ax
|
|
@@ -172,36 +179,43 @@ class LayersMesh(RenderPlan):
|
|
|
172
179
|
for iy, row in enumerate(layer):
|
|
173
180
|
for ix, v in enumerate(row):
|
|
174
181
|
if v:
|
|
175
|
-
art = piece.draw(
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
art = piece.draw(
|
|
183
|
+
ix + self.x_offset,
|
|
184
|
+
iy + self.y_offset,
|
|
185
|
+
self.width,
|
|
186
|
+
self.height,
|
|
187
|
+
ax,
|
|
188
|
+
)
|
|
178
189
|
ax.add_artist(art)
|
|
179
190
|
else:
|
|
180
191
|
for iy, row in enumerate(data):
|
|
181
192
|
for ix, v in enumerate(row):
|
|
182
193
|
piece = self.pieces_mapper[v]
|
|
183
|
-
art = piece.draw(
|
|
184
|
-
|
|
194
|
+
art = piece.draw(
|
|
195
|
+
ix + self.x_offset,
|
|
196
|
+
iy + self.y_offset,
|
|
197
|
+
self.width,
|
|
198
|
+
self.height,
|
|
199
|
+
ax,
|
|
200
|
+
)
|
|
185
201
|
ax.add_artist(art)
|
|
186
202
|
ax.invert_yaxis()
|
|
187
203
|
|
|
188
204
|
|
|
189
205
|
class Layers(ClusterBoard):
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
mesh = LayersMesh(data=data, layers=layers, pieces=pieces,
|
|
204
|
-
shrink=shrink)
|
|
206
|
+
def __init__(
|
|
207
|
+
self,
|
|
208
|
+
data=None,
|
|
209
|
+
layers=None,
|
|
210
|
+
pieces=None,
|
|
211
|
+
cluster_data=None,
|
|
212
|
+
shrink=(1.0, 1.0),
|
|
213
|
+
height=None,
|
|
214
|
+
width=None,
|
|
215
|
+
aspect=1.0,
|
|
216
|
+
name=None,
|
|
217
|
+
):
|
|
218
|
+
mesh = LayersMesh(data=data, layers=layers, pieces=pieces, shrink=shrink)
|
|
205
219
|
if cluster_data is None:
|
|
206
220
|
self._allow_cluster = False
|
|
207
221
|
data_shape = mesh.get_data()[0].shape
|
|
@@ -235,8 +249,8 @@ class Piece:
|
|
|
235
249
|
|
|
236
250
|
@staticmethod
|
|
237
251
|
def draw_center(x, y, w, h):
|
|
238
|
-
cx = x + w / 2.
|
|
239
|
-
cy = y + h / 2.
|
|
252
|
+
cx = x + w / 2.0
|
|
253
|
+
cy = y + h / 2.0
|
|
240
254
|
return cx, cy
|
|
241
255
|
|
|
242
256
|
def draw(self, x, y, w, h, ax) -> Artist:
|
|
@@ -254,7 +268,6 @@ class Piece:
|
|
|
254
268
|
|
|
255
269
|
|
|
256
270
|
class Rect(Piece):
|
|
257
|
-
|
|
258
271
|
def __init__(self, color="C0", label=None, legend=True, zorder=0):
|
|
259
272
|
self.color = color
|
|
260
273
|
self.label = label
|
|
@@ -262,16 +275,16 @@ class Rect(Piece):
|
|
|
262
275
|
self.zorder = zorder
|
|
263
276
|
|
|
264
277
|
def __repr__(self):
|
|
265
|
-
return
|
|
266
|
-
|
|
278
|
+
return (
|
|
279
|
+
f"{self.__class__.__name__}(color='{self.color}', " f"label='{self.label}')"
|
|
280
|
+
)
|
|
267
281
|
|
|
268
282
|
def draw(self, x, y, w, h, ax) -> Artist:
|
|
269
283
|
return Rectangle((x, y), w, h, facecolor=self.color)
|
|
270
284
|
|
|
271
285
|
|
|
272
286
|
class FracRect(Piece):
|
|
273
|
-
def __init__(self, color="C0", frac=(.9, .5), label=None, legend=True,
|
|
274
|
-
zorder=0):
|
|
287
|
+
def __init__(self, color="C0", frac=(0.9, 0.5), label=None, legend=True, zorder=0):
|
|
275
288
|
self.color = color
|
|
276
289
|
self.label = label
|
|
277
290
|
self.frac = frac
|
|
@@ -279,16 +292,17 @@ class FracRect(Piece):
|
|
|
279
292
|
self.zorder = zorder
|
|
280
293
|
|
|
281
294
|
def __repr__(self):
|
|
282
|
-
return
|
|
283
|
-
|
|
295
|
+
return (
|
|
296
|
+
f"{self.__class__.__name__}(color='{self.color}', " f"label='{self.label}')"
|
|
297
|
+
)
|
|
284
298
|
|
|
285
299
|
def draw(self, x, y, w, h, ax):
|
|
286
300
|
fx, fy = self.frac
|
|
287
301
|
draw_w, draw_h = w * fx, h * fy
|
|
288
302
|
# compute the actual drawing bbox
|
|
289
303
|
# Lower-left corner
|
|
290
|
-
draw_x = x + (w - draw_w) / 2.
|
|
291
|
-
draw_y = y + (h - draw_h) / 2.
|
|
304
|
+
draw_x = x + (w - draw_w) / 2.0
|
|
305
|
+
draw_y = y + (h - draw_h) / 2.0
|
|
292
306
|
return Rectangle((draw_x, draw_y), draw_w, draw_h, fc=self.color)
|
|
293
307
|
|
|
294
308
|
|
|
@@ -301,14 +315,10 @@ class FrameRect(Piece):
|
|
|
301
315
|
self.zorder = zorder
|
|
302
316
|
|
|
303
317
|
def __repr__(self):
|
|
304
|
-
return f"{self.__class__.__name__}(color={self.color}, "
|
|
305
|
-
f"label={self.label})"
|
|
318
|
+
return f"{self.__class__.__name__}(color={self.color}, " f"label={self.label})"
|
|
306
319
|
|
|
307
320
|
def draw(self, x, y, w, h, ax):
|
|
308
|
-
return Rectangle((x, y), w, h,
|
|
309
|
-
fill=False,
|
|
310
|
-
ec=self.color,
|
|
311
|
-
linewidth=self.width)
|
|
321
|
+
return Rectangle((x, y), w, h, fill=False, ec=self.color, linewidth=self.width)
|
|
312
322
|
|
|
313
323
|
|
|
314
324
|
class RightTri(Piece):
|
|
@@ -319,8 +329,9 @@ class RightTri(Piece):
|
|
|
319
329
|
"upper right": [1, 2, 3],
|
|
320
330
|
}
|
|
321
331
|
|
|
322
|
-
def __init__(
|
|
323
|
-
|
|
332
|
+
def __init__(
|
|
333
|
+
self, color="C0", right_angle="lower left", label=None, legend=True, zorder=0
|
|
334
|
+
):
|
|
324
335
|
self.color = color
|
|
325
336
|
self.pos = right_angle
|
|
326
337
|
self.label = label
|
|
@@ -328,8 +339,7 @@ class RightTri(Piece):
|
|
|
328
339
|
self.zorder = zorder
|
|
329
340
|
|
|
330
341
|
def __repr__(self):
|
|
331
|
-
return f"{self.__class__.__name__}(color={self.color}, "
|
|
332
|
-
f"label={self.label})"
|
|
342
|
+
return f"{self.__class__.__name__}(color={self.color}, " f"label={self.label})"
|
|
333
343
|
|
|
334
344
|
def draw(self, x, y, w, h, ax):
|
|
335
345
|
p0 = (x, y)
|
|
@@ -342,22 +352,20 @@ class RightTri(Piece):
|
|
|
342
352
|
|
|
343
353
|
|
|
344
354
|
class Marker(Piece):
|
|
345
|
-
|
|
346
|
-
def __init__(self, marker, color="C0", size=32,
|
|
347
|
-
label=None, legend=True, zorder=0):
|
|
355
|
+
def __init__(self, marker, color="C0", size=32, label=None, legend=True, zorder=0):
|
|
348
356
|
self.color = color
|
|
349
357
|
self.label = label
|
|
350
358
|
self.legend_entry = legend
|
|
351
359
|
self.zorder = zorder
|
|
352
360
|
self.size = size
|
|
353
361
|
m = MarkerStyle(marker)
|
|
354
|
-
self.path = m.get_path().transformed(
|
|
355
|
-
m.get_transform())
|
|
362
|
+
self.path = m.get_path().transformed(m.get_transform())
|
|
356
363
|
|
|
357
364
|
def draw(self, x, y, w, h, ax):
|
|
358
365
|
c = self.draw_center(x, y, w, h)
|
|
359
366
|
collection = PathCollection(
|
|
360
|
-
(self.path,),
|
|
367
|
+
(self.path,),
|
|
368
|
+
[self.size],
|
|
361
369
|
offsets=[c],
|
|
362
370
|
offset_transform=ax.transData,
|
|
363
371
|
facecolors=self.color,
|
|
@@ -367,9 +375,9 @@ class Marker(Piece):
|
|
|
367
375
|
return collection
|
|
368
376
|
|
|
369
377
|
def legend(self, x, y, w, h):
|
|
370
|
-
return Line2D(
|
|
371
|
-
|
|
372
|
-
|
|
378
|
+
return Line2D(
|
|
379
|
+
[0], [0], marker=self.marker, color=self.color, markersize=self.size
|
|
380
|
+
)
|
|
373
381
|
|
|
374
382
|
|
|
375
383
|
def preview(piece: Piece, figsize=(1, 1)):
|