cellestial 0.45.0__tar.gz → 0.46.0__tar.gz
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.
- {cellestial-0.45.0 → cellestial-0.46.0}/PKG-INFO +1 -1
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/dimensional.py +2 -2
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/distribution.py +3 -4
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/_rank_genes_groups.py +3 -4
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/dotplot.py +24 -16
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/heatmap.py +33 -32
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/stacked_violin.py +14 -16
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/spatial/spatial.py +3 -3
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/__init__.py +2 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/errors.py +4 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/utilities.py +41 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/pyproject.toml +1 -1
- {cellestial-0.45.0 → cellestial-0.46.0}/LICENSE +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/README.md +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/_version.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/datasets/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/datasets/datasets.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/frames/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/frames/build.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/frames/operations.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/_deferred.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/arrow.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/bracket.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/ondata_legend.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/outline.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/stream.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/layers/utilities.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/base/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/base/base.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/basic/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/basic/bar.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/basic/scatter.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/common/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/common/xyplot.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/common/xyplots.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/distributions.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/subdimensional.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/core/subdimensionals.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/differential/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/differential/markers.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/differential/volcano.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/heatmap/_key_groups.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/quick/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/quick/elbow.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/quick/highest.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/single/quick/ridge.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/spatial/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/spatial/_components.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/spatial/spatials.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/themes/__init__.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/themes/_distributions.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/themes/_heatmaps.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/themes/_scatters.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/colors.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/dendrogram.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/operations.py +0 -0
- {cellestial-0.45.0 → cellestial-0.46.0}/cellestial/util/save.py +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Sequence
|
|
5
4
|
from typing import TYPE_CHECKING, Literal
|
|
6
5
|
|
|
@@ -27,6 +26,7 @@ from cellestial.util import (
|
|
|
27
26
|
_is_variable_key,
|
|
28
27
|
_resolve_tooltips,
|
|
29
28
|
_validate_tooltips,
|
|
29
|
+
_warn,
|
|
30
30
|
)
|
|
31
31
|
from cellestial.util.errors import UnsupportedDataTypeError
|
|
32
32
|
|
|
@@ -335,6 +335,6 @@ def dimensional(
|
|
|
335
335
|
)
|
|
336
336
|
elif frame[key].dtype != pl.Categorical:
|
|
337
337
|
msg = f"key `{key}` is not categorical, legend on data will not be added"
|
|
338
|
-
|
|
338
|
+
_warn(msg)
|
|
339
339
|
|
|
340
340
|
return scttr
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from typing import TYPE_CHECKING, Any, Literal
|
|
5
|
-
from warnings import warn
|
|
6
5
|
|
|
7
6
|
import polars as pl
|
|
8
7
|
from anndata import AnnData
|
|
@@ -27,6 +26,7 @@ from cellestial.util import (
|
|
|
27
26
|
_resolve_tooltips,
|
|
28
27
|
_select_variable_keys,
|
|
29
28
|
_validate_tooltips,
|
|
29
|
+
_warn,
|
|
30
30
|
)
|
|
31
31
|
from cellestial.util.errors import UnsupportedDataTypeError
|
|
32
32
|
|
|
@@ -131,11 +131,10 @@ def _distribution(
|
|
|
131
131
|
if group_by is None:
|
|
132
132
|
group_by = variable_column
|
|
133
133
|
elif len(keys) > 1 and group_by != variable_column:
|
|
134
|
-
|
|
134
|
+
_warn(
|
|
135
135
|
f"Multiple keys provided; `group_by={group_by!r}` cannot share the "
|
|
136
136
|
f"x-axis with the variable column. Falling back to "
|
|
137
|
-
f"`group_by={variable_column!r}`. For a per-key panel, use the plural variant."
|
|
138
|
-
stacklevel=3,
|
|
137
|
+
f"`group_by={variable_column!r}`. For a per-key panel, use the plural variant."
|
|
139
138
|
)
|
|
140
139
|
group_by = variable_column
|
|
141
140
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
|
-
from warnings import warn
|
|
5
4
|
|
|
6
5
|
from anndata import AnnData
|
|
7
6
|
|
|
7
|
+
from cellestial.util import _warn
|
|
8
8
|
from cellestial.util.errors import KeyNotFoundError, UnsupportedDataTypeError
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
@@ -124,13 +124,12 @@ def _extract_rank_genes_groups(
|
|
|
124
124
|
for gene, first, later in dropped[:3]
|
|
125
125
|
)
|
|
126
126
|
suffix = f" and {len(dropped) - 3} more" if len(dropped) > 3 else ""
|
|
127
|
-
|
|
127
|
+
_warn(
|
|
128
128
|
"Some genes ranked highly in multiple groups; "
|
|
129
129
|
"keeping the first occurrence and dropping the rest "
|
|
130
130
|
f"({examples}{suffix}). "
|
|
131
131
|
"Increase `n_genes`, restrict `groups`, "
|
|
132
|
-
"or pass an explicit `keys` mapping to control this."
|
|
133
|
-
stacklevel=2,
|
|
132
|
+
"or pass an explicit `keys` mapping to control this."
|
|
134
133
|
)
|
|
135
134
|
|
|
136
135
|
params = record["params"]
|
|
@@ -35,6 +35,7 @@ from cellestial.util import (
|
|
|
35
35
|
_get_dendrogram_path_frame,
|
|
36
36
|
_resolve_tooltips,
|
|
37
37
|
_validate_tooltips,
|
|
38
|
+
_warn,
|
|
38
39
|
)
|
|
39
40
|
from cellestial.util.errors import UnsupportedDataTypeError
|
|
40
41
|
|
|
@@ -49,7 +50,7 @@ def dotplot(
|
|
|
49
50
|
keys: Sequence[str] | Mapping[str, Sequence[str]] | None = None,
|
|
50
51
|
group_by: str | None = None,
|
|
51
52
|
*,
|
|
52
|
-
|
|
53
|
+
markers: bool | str = False,
|
|
53
54
|
n_genes: int = 5,
|
|
54
55
|
groups: Sequence[str] | None = None,
|
|
55
56
|
mapping: FeatureSpec | None = None,
|
|
@@ -90,22 +91,20 @@ def dotplot(
|
|
|
90
91
|
data : AnnData
|
|
91
92
|
The AnnData object of the single cell data.
|
|
92
93
|
keys : Sequence[str] | Mapping[str, Sequence[str]] | None, default=None
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
key cannot appear in more than one group. Must be ``None`` when
|
|
97
|
-
``rank_genes_groups`` is set.
|
|
94
|
+
Variable keys to include, placed on the x-axis. A mapping assigns
|
|
95
|
+
keys to group labels (no key in more than one group). Must be
|
|
96
|
+
``None`` when ``markers`` is set.
|
|
98
97
|
group_by : str | None, default=None
|
|
99
98
|
The key to group the data by. Inferred from a precomputed ranking
|
|
100
|
-
when ``
|
|
101
|
-
|
|
99
|
+
when ``markers`` is set.
|
|
100
|
+
markers : bool | str, default=False
|
|
102
101
|
Derive ``keys`` from a precomputed ranking. Pass ``True`` to use the
|
|
103
102
|
default ranking key, or a string to read a custom key (e.g.
|
|
104
103
|
``"rank_genes_groups_wilcoxon"``).
|
|
105
104
|
n_genes : int, default=5
|
|
106
|
-
Number of top genes to take per group when ``
|
|
105
|
+
Number of top genes to take per group when ``markers`` is set.
|
|
107
106
|
groups : Sequence[str] | None, default=None
|
|
108
|
-
Subset of groups to include when ``
|
|
107
|
+
Subset of groups to include when ``markers`` is set;
|
|
109
108
|
``None`` keeps all groups in their stored order.
|
|
110
109
|
mapping : FeatureSpec | None, default=None
|
|
111
110
|
Aesthetic mappings for the plot, the result of `aes()`.
|
|
@@ -187,12 +186,12 @@ def dotplot(
|
|
|
187
186
|
UnsupportedDataTypeError
|
|
188
187
|
If `data` is not a supported single-cell data object.
|
|
189
188
|
KeyNotFoundError
|
|
190
|
-
If `
|
|
189
|
+
If `markers` is enabled and the requested ranking result or
|
|
191
190
|
group is missing.
|
|
192
191
|
DuplicateKeysError
|
|
193
192
|
If a mapping passed to `keys` assigns the same key to multiple groups.
|
|
194
193
|
ValueError
|
|
195
|
-
If `keys` and `group_by` are missing while `
|
|
194
|
+
If `keys` and `group_by` are missing while `markers` is
|
|
196
195
|
disabled.
|
|
197
196
|
|
|
198
197
|
Examples
|
|
@@ -253,7 +252,7 @@ def dotplot(
|
|
|
253
252
|
.. jupyter-execute::
|
|
254
253
|
|
|
255
254
|
sc.tl.rank_genes_groups(data, groupby="cell_type_lvl1")
|
|
256
|
-
cl.dotplot(data,
|
|
255
|
+
cl.dotplot(data, markers=True, n_genes=5)
|
|
257
256
|
|
|
258
257
|
"""
|
|
259
258
|
# HANDLE: Data types
|
|
@@ -261,10 +260,10 @@ def dotplot(
|
|
|
261
260
|
msg = f"Unsupported data type: `{type(data)}`"
|
|
262
261
|
raise UnsupportedDataTypeError(msg)
|
|
263
262
|
|
|
264
|
-
if
|
|
263
|
+
if markers:
|
|
265
264
|
keys, group_by = _resolve_rank_genes_groups_args(
|
|
266
265
|
data,
|
|
267
|
-
rank_genes_groups=
|
|
266
|
+
rank_genes_groups=markers,
|
|
268
267
|
n_genes=n_genes,
|
|
269
268
|
groups=groups,
|
|
270
269
|
keys=keys,
|
|
@@ -273,7 +272,7 @@ def dotplot(
|
|
|
273
272
|
elif keys is None or group_by is None:
|
|
274
273
|
msg = (
|
|
275
274
|
"`keys` and `group_by` are required "
|
|
276
|
-
"(or enable `
|
|
275
|
+
"(or enable `markers` to derive them)."
|
|
277
276
|
)
|
|
278
277
|
raise ValueError(msg)
|
|
279
278
|
|
|
@@ -288,6 +287,15 @@ def dotplot(
|
|
|
288
287
|
axis=0,
|
|
289
288
|
variable_keys=keys,
|
|
290
289
|
)
|
|
290
|
+
# WARN: negative expression makes the percent-expressed (dot size) misleading
|
|
291
|
+
overall_min = frame.select(pl.min_horizontal(pl.col(keys).min())).item()
|
|
292
|
+
if overall_min is not None and overall_min < 0:
|
|
293
|
+
_warn(
|
|
294
|
+
"Expression matrix contains negative values, which suggests scaled data. "
|
|
295
|
+
"Dot size (percentage of cells above `threshold`, default 0) assumes "
|
|
296
|
+
"non-negative expression and may be misleading here; pass raw or "
|
|
297
|
+
"log-normalized expression, or set `threshold` explicitly."
|
|
298
|
+
)
|
|
291
299
|
# DROP: rows with null group_by to avoid null labels downstream
|
|
292
300
|
frame = frame.filter(pl.col(group_by).is_not_null())
|
|
293
301
|
index_columns = [x for x in frame.columns if x not in keys]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, Literal
|
|
4
|
-
from warnings import warn
|
|
5
4
|
|
|
6
5
|
import polars as pl
|
|
7
6
|
from anndata import AnnData
|
|
@@ -29,7 +28,12 @@ from cellestial.single.heatmap._key_groups import (
|
|
|
29
28
|
)
|
|
30
29
|
from cellestial.single.heatmap._rank_genes_groups import _resolve_rank_genes_groups_args
|
|
31
30
|
from cellestial.themes import _THEME_HEATMAP
|
|
32
|
-
from cellestial.util import
|
|
31
|
+
from cellestial.util import (
|
|
32
|
+
_fill_gradient,
|
|
33
|
+
_get_dendrogram,
|
|
34
|
+
_get_dendrogram_path_frame,
|
|
35
|
+
_warn,
|
|
36
|
+
)
|
|
33
37
|
from cellestial.util.errors import UnsupportedDataTypeError
|
|
34
38
|
|
|
35
39
|
if TYPE_CHECKING:
|
|
@@ -188,7 +192,7 @@ def heatmap(
|
|
|
188
192
|
keys: Sequence[str] | Mapping[str, Sequence[str]] | None = None,
|
|
189
193
|
group_by: str | None = None,
|
|
190
194
|
*,
|
|
191
|
-
|
|
195
|
+
markers: bool | str = False,
|
|
192
196
|
n_genes: int = 5,
|
|
193
197
|
groups: Sequence[str] | None = None,
|
|
194
198
|
mapping: FeatureSpec | None = None,
|
|
@@ -233,21 +237,20 @@ def heatmap(
|
|
|
233
237
|
data : AnnData
|
|
234
238
|
The AnnData object of the single cell data.
|
|
235
239
|
keys : Sequence[str] | Mapping[str, Sequence[str]] | None, default=None
|
|
236
|
-
Variable keys to include
|
|
237
|
-
group
|
|
238
|
-
|
|
239
|
-
than one group. Must be ``None`` when ``rank_genes_groups`` is set.
|
|
240
|
+
Variable keys to include, placed on the x-axis. A mapping assigns
|
|
241
|
+
keys to group labels (no key in more than one group). Must be
|
|
242
|
+
``None`` when ``markers`` is set.
|
|
240
243
|
group_by : str | None, default=None
|
|
241
244
|
The key to group the data by. Inferred from a precomputed ranking
|
|
242
|
-
when ``
|
|
243
|
-
|
|
245
|
+
when ``markers`` is set.
|
|
246
|
+
markers : bool | str, default=False
|
|
244
247
|
Derive ``keys`` from a precomputed ranking. Pass ``True`` to use the
|
|
245
248
|
default ranking key, or a string to read a custom key (e.g.
|
|
246
249
|
``"rank_genes_groups_wilcoxon"``).
|
|
247
250
|
n_genes : int, default=5
|
|
248
|
-
Number of top genes to take per group when ``
|
|
251
|
+
Number of top genes to take per group when ``markers`` is set.
|
|
249
252
|
groups : Sequence[str] | None, default=None
|
|
250
|
-
Subset of groups to include when ``
|
|
253
|
+
Subset of groups to include when ``markers`` is set;
|
|
251
254
|
``None`` keeps all groups in their stored order.
|
|
252
255
|
mapping : FeatureSpec | None, default=None
|
|
253
256
|
Aesthetic mappings for the plot, the result of `aes()`.
|
|
@@ -338,12 +341,12 @@ def heatmap(
|
|
|
338
341
|
UnsupportedDataTypeError
|
|
339
342
|
If `data` is not a supported single-cell data object.
|
|
340
343
|
KeyNotFoundError
|
|
341
|
-
If `
|
|
344
|
+
If `markers` is enabled and the requested ranking result or
|
|
342
345
|
group is missing.
|
|
343
346
|
DuplicateKeysError
|
|
344
347
|
If a mapping passed to `keys` assigns the same key to multiple groups.
|
|
345
348
|
ValueError
|
|
346
|
-
If `keys` and `group_by` are missing while `
|
|
349
|
+
If `keys` and `group_by` are missing while `markers` is
|
|
347
350
|
disabled.
|
|
348
351
|
|
|
349
352
|
Examples
|
|
@@ -426,7 +429,7 @@ def heatmap(
|
|
|
426
429
|
)
|
|
427
430
|
|
|
428
431
|
To plot the top genes from a precomputed ranking, set
|
|
429
|
-
``
|
|
432
|
+
``markers`` and ``n_genes`` (``keys`` and ``group_by`` are
|
|
430
433
|
inferred):
|
|
431
434
|
|
|
432
435
|
.. jupyter-execute::
|
|
@@ -434,17 +437,17 @@ def heatmap(
|
|
|
434
437
|
import scanpy as sc
|
|
435
438
|
|
|
436
439
|
sc.tl.rank_genes_groups(data, groupby="cell_type_lvl1")
|
|
437
|
-
cl.heatmap(data,
|
|
440
|
+
cl.heatmap(data, markers=True, n_genes=5, aggregate=True)
|
|
438
441
|
|
|
439
442
|
"""
|
|
440
443
|
if not isinstance(data, AnnData):
|
|
441
444
|
msg = f"Unsupported data type: `{type(data)}`"
|
|
442
445
|
raise UnsupportedDataTypeError(msg)
|
|
443
446
|
|
|
444
|
-
if
|
|
447
|
+
if markers:
|
|
445
448
|
keys, group_by = _resolve_rank_genes_groups_args(
|
|
446
449
|
data,
|
|
447
|
-
rank_genes_groups=
|
|
450
|
+
rank_genes_groups=markers,
|
|
448
451
|
n_genes=n_genes,
|
|
449
452
|
groups=groups,
|
|
450
453
|
keys=keys,
|
|
@@ -453,17 +456,16 @@ def heatmap(
|
|
|
453
456
|
elif keys is None or group_by is None:
|
|
454
457
|
msg = (
|
|
455
458
|
"`keys` and `group_by` are required "
|
|
456
|
-
"(or enable `
|
|
459
|
+
"(or enable `markers` to derive them)."
|
|
457
460
|
)
|
|
458
461
|
raise ValueError(msg)
|
|
459
462
|
|
|
460
463
|
mapping = mapping or aes()
|
|
461
464
|
|
|
462
465
|
if "tooltips" in geom_kwargs and geom == "raster":
|
|
463
|
-
|
|
466
|
+
_warn(
|
|
464
467
|
"\nWarning: tooltips are not supported for 'raster' geom and will be ignored."
|
|
465
|
-
"\nUse 'tile' geom to enable tooltips."
|
|
466
|
-
stacklevel=1,
|
|
468
|
+
"\nUse 'tile' geom to enable tooltips."
|
|
467
469
|
)
|
|
468
470
|
geom_kwargs.pop("tooltips")
|
|
469
471
|
|
|
@@ -649,7 +651,7 @@ def matrixplot(
|
|
|
649
651
|
keys: Sequence[str] | Mapping[str, Sequence[str]] | None = None,
|
|
650
652
|
group_by: str | None = None,
|
|
651
653
|
*,
|
|
652
|
-
|
|
654
|
+
markers: bool | str = False,
|
|
653
655
|
n_genes: int = 5,
|
|
654
656
|
groups: Sequence[str] | None = None,
|
|
655
657
|
mapping: FeatureSpec | None = None,
|
|
@@ -692,21 +694,20 @@ def matrixplot(
|
|
|
692
694
|
data : AnnData
|
|
693
695
|
The AnnData object of the single cell data.
|
|
694
696
|
keys : Sequence[str] | Mapping[str, Sequence[str]] | None, default=None
|
|
695
|
-
Variable keys to include
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
than one group. Must be ``None`` when ``rank_genes_groups`` is set.
|
|
697
|
+
Variable keys to include, placed on the x-axis. A mapping assigns
|
|
698
|
+
keys to group labels (no key in more than one group). Must be
|
|
699
|
+
``None`` when ``markers`` is set.
|
|
699
700
|
group_by : str | None, default=None
|
|
700
701
|
The key to group the data by. Inferred from a precomputed ranking
|
|
701
|
-
when ``
|
|
702
|
-
|
|
702
|
+
when ``markers`` is set.
|
|
703
|
+
markers : bool | str, default=False
|
|
703
704
|
Derive ``keys`` from a precomputed ranking. Pass ``True`` to use the
|
|
704
705
|
default ranking key, or a string to read a custom key (e.g.
|
|
705
706
|
``"rank_genes_groups_wilcoxon"``).
|
|
706
707
|
n_genes : int, default=5
|
|
707
|
-
Number of top genes to take per group when ``
|
|
708
|
+
Number of top genes to take per group when ``markers`` is set.
|
|
708
709
|
groups : Sequence[str] | None, default=None
|
|
709
|
-
Subset of groups to include when ``
|
|
710
|
+
Subset of groups to include when ``markers`` is set;
|
|
710
711
|
``None`` keeps all groups in their stored order.
|
|
711
712
|
mapping : FeatureSpec | None, default=None
|
|
712
713
|
Aesthetic mappings for the plot, the result of `aes()`.
|
|
@@ -817,13 +818,13 @@ def matrixplot(
|
|
|
817
818
|
.. jupyter-execute::
|
|
818
819
|
|
|
819
820
|
sc.tl.rank_genes_groups(data, groupby="cell_type_lvl1")
|
|
820
|
-
cl.matrixplot(data,
|
|
821
|
+
cl.matrixplot(data, markers=True, n_genes=5)
|
|
821
822
|
"""
|
|
822
823
|
return heatmap(
|
|
823
824
|
data,
|
|
824
825
|
keys=keys,
|
|
825
826
|
group_by=group_by,
|
|
826
|
-
|
|
827
|
+
markers=markers,
|
|
827
828
|
n_genes=n_genes,
|
|
828
829
|
groups=groups,
|
|
829
830
|
mapping=mapping,
|
|
@@ -179,7 +179,7 @@ def stacked_violin(
|
|
|
179
179
|
keys: Sequence[str] | Mapping[str, Sequence[str]] | None = None,
|
|
180
180
|
group_by: str | None = None,
|
|
181
181
|
*,
|
|
182
|
-
|
|
182
|
+
markers: bool | str = False,
|
|
183
183
|
n_genes: int = 5,
|
|
184
184
|
groups: Sequence[str] | None = None,
|
|
185
185
|
mapping: FeatureSpec | None = None,
|
|
@@ -227,22 +227,20 @@ def stacked_violin(
|
|
|
227
227
|
data : AnnData
|
|
228
228
|
The AnnData object of the single cell data.
|
|
229
229
|
keys : Sequence[str] | Mapping[str, Sequence[str]] | None, default=None
|
|
230
|
-
Variable keys laid out along the x-axis
|
|
231
|
-
key.
|
|
232
|
-
|
|
233
|
-
mapping order. The same key cannot appear in more than one group.
|
|
234
|
-
Must be ``None`` when ``rank_genes_groups`` is set.
|
|
230
|
+
Variable keys laid out along the x-axis, one column of violins per
|
|
231
|
+
key. A mapping assigns keys to group labels (no key in more than one
|
|
232
|
+
group). Must be ``None`` when ``markers`` is set.
|
|
235
233
|
group_by : str | None, default=None
|
|
236
234
|
The key used to group observations along the y-axis. Inferred from a
|
|
237
|
-
precomputed ranking when ``
|
|
238
|
-
|
|
235
|
+
precomputed ranking when ``markers`` is set.
|
|
236
|
+
markers : bool | str, default=False
|
|
239
237
|
Derive ``keys`` from a precomputed ranking. Pass ``True`` to use the
|
|
240
238
|
default ranking key, or a string to read a custom key (e.g.
|
|
241
239
|
``"rank_genes_groups_wilcoxon"``).
|
|
242
240
|
n_genes : int, default=5
|
|
243
|
-
Number of top genes to take per group when ``
|
|
241
|
+
Number of top genes to take per group when ``markers`` is set.
|
|
244
242
|
groups : Sequence[str] | None, default=None
|
|
245
|
-
Subset of groups to include when ``
|
|
243
|
+
Subset of groups to include when ``markers`` is set;
|
|
246
244
|
``None`` keeps all groups in their stored order.
|
|
247
245
|
mapping : FeatureSpec | None, default=None
|
|
248
246
|
Aesthetic mappings for the plot, the result of `aes()`.
|
|
@@ -349,12 +347,12 @@ def stacked_violin(
|
|
|
349
347
|
UnsupportedDataTypeError
|
|
350
348
|
If `data` is not a supported single-cell data object.
|
|
351
349
|
KeyNotFoundError
|
|
352
|
-
If `
|
|
350
|
+
If `markers` is enabled and the requested ranking result or
|
|
353
351
|
group is missing.
|
|
354
352
|
DuplicateKeysError
|
|
355
353
|
If a mapping passed to `keys` assigns the same key to multiple groups.
|
|
356
354
|
ValueError
|
|
357
|
-
If `keys` and `group_by` are missing while `
|
|
355
|
+
If `keys` and `group_by` are missing while `markers` is
|
|
358
356
|
disabled.
|
|
359
357
|
|
|
360
358
|
Examples
|
|
@@ -407,17 +405,17 @@ def stacked_violin(
|
|
|
407
405
|
.. jupyter-execute::
|
|
408
406
|
|
|
409
407
|
sc.tl.rank_genes_groups(data, groupby="cell_type_lvl1")
|
|
410
|
-
cl.stacked_violin(data,
|
|
408
|
+
cl.stacked_violin(data, markers=True, n_genes=5)
|
|
411
409
|
"""
|
|
412
410
|
# HANDLE: Data types
|
|
413
411
|
if not isinstance(data, AnnData):
|
|
414
412
|
msg = f"Unsupported data type: `{type(data)}`"
|
|
415
413
|
raise UnsupportedDataTypeError(msg)
|
|
416
414
|
|
|
417
|
-
if
|
|
415
|
+
if markers:
|
|
418
416
|
keys, group_by = _resolve_rank_genes_groups_args(
|
|
419
417
|
data,
|
|
420
|
-
rank_genes_groups=
|
|
418
|
+
rank_genes_groups=markers,
|
|
421
419
|
n_genes=n_genes,
|
|
422
420
|
groups=groups,
|
|
423
421
|
keys=keys,
|
|
@@ -426,7 +424,7 @@ def stacked_violin(
|
|
|
426
424
|
elif keys is None or group_by is None:
|
|
427
425
|
msg = (
|
|
428
426
|
"`keys` and `group_by` are required "
|
|
429
|
-
"(or enable `
|
|
427
|
+
"(or enable `markers` to derive them)."
|
|
430
428
|
)
|
|
431
429
|
raise ValueError(msg)
|
|
432
430
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Sequence
|
|
5
4
|
from typing import TYPE_CHECKING
|
|
6
5
|
|
|
@@ -30,6 +29,7 @@ from cellestial.util import (
|
|
|
30
29
|
_is_variable_key,
|
|
31
30
|
_resolve_tooltips,
|
|
32
31
|
_validate_tooltips,
|
|
32
|
+
_warn,
|
|
33
33
|
)
|
|
34
34
|
from cellestial.util.errors import UnsupportedDataTypeError
|
|
35
35
|
|
|
@@ -113,7 +113,7 @@ def _spatial_components(
|
|
|
113
113
|
image_array = images.get(image_key)
|
|
114
114
|
if image_array is None:
|
|
115
115
|
msg = f"image `{image_key}` not found for library `{library_id}`"
|
|
116
|
-
|
|
116
|
+
_warn(msg)
|
|
117
117
|
return image_array, spot_coordinates, None, data
|
|
118
118
|
|
|
119
119
|
msg = f"Unsupported data type: `{type(data)}`"
|
|
@@ -408,7 +408,7 @@ def spatial(
|
|
|
408
408
|
frame = frame.filter(pl.col(key).is_in(list(groups)))
|
|
409
409
|
else:
|
|
410
410
|
msg = f"key `{key}` is not categorical, `groups` filter ignored"
|
|
411
|
-
|
|
411
|
+
_warn(msg)
|
|
412
412
|
|
|
413
413
|
# HANDLE: standard scaling (numeric keys only)
|
|
414
414
|
if scale_axis is not None and key is not None and frame[key].dtype.is_numeric():
|
|
@@ -18,6 +18,7 @@ from cellestial.util.utilities import (
|
|
|
18
18
|
_share_ticks,
|
|
19
19
|
_tooltip_fields,
|
|
20
20
|
_validate_tooltips,
|
|
21
|
+
_warn,
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"_share_ticks",
|
|
37
38
|
"_tooltip_fields",
|
|
38
39
|
"_validate_tooltips",
|
|
40
|
+
"_warn",
|
|
39
41
|
"get_mapping",
|
|
40
42
|
"get_slice",
|
|
41
43
|
"retrieve",
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import inspect
|
|
3
4
|
import re
|
|
5
|
+
import warnings
|
|
4
6
|
from collections.abc import Sequence
|
|
5
7
|
from math import ceil, log10
|
|
8
|
+
from pathlib import Path
|
|
6
9
|
from typing import Literal
|
|
7
10
|
|
|
8
11
|
import polars as pl
|
|
@@ -21,6 +24,44 @@ from lets_plot import (
|
|
|
21
24
|
from lets_plot.plot.core import FeatureSpec
|
|
22
25
|
from lets_plot.plot.subplots import SupPlotsSpec
|
|
23
26
|
|
|
27
|
+
from cellestial.util.errors import CellestialWarning
|
|
28
|
+
|
|
29
|
+
_PACKAGE_ROOT = str(Path(__file__).parents[1])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _format_warning(
|
|
33
|
+
message: Warning | str, category: type[Warning], *_args: object
|
|
34
|
+
) -> str:
|
|
35
|
+
"""Render a cellestial warning as one line, dropping the source location."""
|
|
36
|
+
return f"{category.__name__}: {message}\n"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _warn(message: str) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Emit a ``CellestialWarning`` rendered without the source location.
|
|
42
|
+
|
|
43
|
+
The warning is still attributed to the first caller outside cellestial so
|
|
44
|
+
``warnings`` filters and per-location de-duplication behave sensibly, but
|
|
45
|
+
it is displayed as a single clean line.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
message : str
|
|
50
|
+
The warning message.
|
|
51
|
+
"""
|
|
52
|
+
caller = inspect.currentframe()
|
|
53
|
+
caller = caller.f_back if caller is not None else None
|
|
54
|
+
stacklevel = 2
|
|
55
|
+
while caller is not None and caller.f_code.co_filename.startswith(_PACKAGE_ROOT):
|
|
56
|
+
stacklevel += 1
|
|
57
|
+
caller = caller.f_back
|
|
58
|
+
original_format = warnings.formatwarning
|
|
59
|
+
warnings.formatwarning = _format_warning
|
|
60
|
+
try:
|
|
61
|
+
warnings.warn(message, CellestialWarning, stacklevel=stacklevel)
|
|
62
|
+
finally:
|
|
63
|
+
warnings.formatwarning = original_format
|
|
64
|
+
|
|
24
65
|
|
|
25
66
|
def _build_tooltips(
|
|
26
67
|
*,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|