pertpy 0.6.0__py3-none-any.whl → 0.8.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.
- pertpy/__init__.py +4 -2
- pertpy/data/__init__.py +66 -1
- pertpy/data/_dataloader.py +28 -26
- pertpy/data/_datasets.py +261 -92
- pertpy/metadata/__init__.py +6 -0
- pertpy/metadata/_cell_line.py +795 -0
- pertpy/metadata/_compound.py +128 -0
- pertpy/metadata/_drug.py +238 -0
- pertpy/metadata/_look_up.py +569 -0
- pertpy/metadata/_metadata.py +70 -0
- pertpy/metadata/_moa.py +125 -0
- pertpy/plot/__init__.py +0 -13
- pertpy/preprocessing/__init__.py +2 -0
- pertpy/preprocessing/_guide_rna.py +89 -6
- pertpy/tools/__init__.py +48 -15
- pertpy/tools/_augur.py +329 -32
- pertpy/tools/_cinemaot.py +145 -6
- pertpy/tools/_coda/_base_coda.py +1237 -116
- pertpy/tools/_coda/_sccoda.py +66 -36
- pertpy/tools/_coda/_tasccoda.py +46 -39
- pertpy/tools/_dialogue.py +180 -77
- pertpy/tools/_differential_gene_expression/__init__.py +20 -0
- pertpy/tools/_differential_gene_expression/_base.py +657 -0
- pertpy/tools/_differential_gene_expression/_checks.py +41 -0
- pertpy/tools/_differential_gene_expression/_dge_comparison.py +86 -0
- pertpy/tools/_differential_gene_expression/_edger.py +125 -0
- pertpy/tools/_differential_gene_expression/_formulaic.py +189 -0
- pertpy/tools/_differential_gene_expression/_pydeseq2.py +95 -0
- pertpy/tools/_differential_gene_expression/_simple_tests.py +162 -0
- pertpy/tools/_differential_gene_expression/_statsmodels.py +72 -0
- pertpy/tools/_distances/_distance_tests.py +29 -24
- pertpy/tools/_distances/_distances.py +584 -98
- pertpy/tools/_enrichment.py +460 -0
- pertpy/tools/_kernel_pca.py +1 -1
- pertpy/tools/_milo.py +406 -49
- pertpy/tools/_mixscape.py +677 -55
- pertpy/tools/_perturbation_space/_clustering.py +10 -3
- pertpy/tools/_perturbation_space/_comparison.py +112 -0
- pertpy/tools/_perturbation_space/_discriminator_classifiers.py +524 -0
- pertpy/tools/_perturbation_space/_perturbation_space.py +146 -52
- pertpy/tools/_perturbation_space/_simple.py +52 -11
- pertpy/tools/_scgen/__init__.py +1 -1
- pertpy/tools/_scgen/_base_components.py +2 -3
- pertpy/tools/_scgen/_scgen.py +706 -0
- pertpy/tools/_scgen/_utils.py +3 -5
- pertpy/tools/decoupler_LICENSE +674 -0
- {pertpy-0.6.0.dist-info → pertpy-0.8.0.dist-info}/METADATA +48 -20
- pertpy-0.8.0.dist-info/RECORD +57 -0
- {pertpy-0.6.0.dist-info → pertpy-0.8.0.dist-info}/WHEEL +1 -1
- pertpy/plot/_augur.py +0 -234
- pertpy/plot/_cinemaot.py +0 -81
- pertpy/plot/_coda.py +0 -1001
- pertpy/plot/_dialogue.py +0 -91
- pertpy/plot/_guide_rna.py +0 -82
- pertpy/plot/_milopy.py +0 -284
- pertpy/plot/_mixscape.py +0 -594
- pertpy/plot/_scgen.py +0 -337
- pertpy/tools/_differential_gene_expression.py +0 -99
- pertpy/tools/_metadata/__init__.py +0 -0
- pertpy/tools/_metadata/_cell_line.py +0 -613
- pertpy/tools/_metadata/_look_up.py +0 -342
- pertpy/tools/_perturbation_space/_discriminator_classifier.py +0 -381
- pertpy/tools/_scgen/_jax_scgen.py +0 -370
- pertpy-0.6.0.dist-info/RECORD +0 -50
- /pertpy/tools/_scgen/{_jax_scgenvae.py → _scgenvae.py} +0 -0
- {pertpy-0.6.0.dist-info → pertpy-0.8.0.dist-info}/licenses/LICENSE +0 -0
pertpy/plot/_dialogue.py
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
import matplotlib.pyplot as plt
|
2
|
-
import pandas as pd
|
3
|
-
import scanpy as sc
|
4
|
-
import seaborn as sns
|
5
|
-
from anndata import AnnData
|
6
|
-
from seaborn import PairGrid
|
7
|
-
|
8
|
-
|
9
|
-
class DialoguePlot:
|
10
|
-
@staticmethod
|
11
|
-
def split_violins(
|
12
|
-
adata: AnnData,
|
13
|
-
split_key: str,
|
14
|
-
celltype_key=str,
|
15
|
-
split_which: tuple[str, str] = None,
|
16
|
-
mcp: str = "mcp_0",
|
17
|
-
) -> plt.Axes:
|
18
|
-
"""Plots split violin plots for a given MCP and split variable.
|
19
|
-
|
20
|
-
Any cells with a value for split_key not in split_which are removed from the plot.
|
21
|
-
|
22
|
-
Args:
|
23
|
-
adata: Annotated data object.
|
24
|
-
split_key: Variable in adata.obs used to split the data.
|
25
|
-
celltype_key: Key for cell type annotations.
|
26
|
-
split_which: Which values of split_key to plot. Required if more than 2 values in split_key.
|
27
|
-
mcp: Key for MCP data. Defaults to "mcp_0".
|
28
|
-
|
29
|
-
Returns:
|
30
|
-
A :class:`~matplotlib.axes.Axes` object
|
31
|
-
|
32
|
-
Examples:
|
33
|
-
>>> import pertpy as pt
|
34
|
-
>>> import scanpy as sc
|
35
|
-
>>> adata = pt.dt.dialogue_example()
|
36
|
-
>>> sc.pp.pca(adata)
|
37
|
-
>>> dl = pt.tl.Dialogue(sample_id = "clinical.status", celltype_key = "cell.subtypes", \
|
38
|
-
n_counts_key = "nCount_RNA", n_mpcs = 3)
|
39
|
-
>>> adata, mcps, ws, ct_subs = dl.calculate_multifactor_PMD(adata, normalize=True)
|
40
|
-
>>> pt.pl.dl.split_violins(adata, split_key='gender', celltype_key='cell.subtypes')
|
41
|
-
"""
|
42
|
-
df = sc.get.obs_df(adata, [celltype_key, mcp, split_key])
|
43
|
-
if split_which is None:
|
44
|
-
split_which = df[split_key].unique()
|
45
|
-
df = df[df[split_key].isin(split_which)]
|
46
|
-
df[split_key] = df[split_key].cat.remove_unused_categories()
|
47
|
-
|
48
|
-
ax = sns.violinplot(data=df, x=celltype_key, y=mcp, hue=split_key, split=True)
|
49
|
-
|
50
|
-
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
|
51
|
-
|
52
|
-
return ax
|
53
|
-
|
54
|
-
@staticmethod
|
55
|
-
def pairplot(adata: AnnData, celltype_key: str, color: str, sample_id: str, mcp: str = "mcp_0") -> PairGrid:
|
56
|
-
"""Generate a pairplot visualization for multi-cell perturbation (MCP) data.
|
57
|
-
|
58
|
-
Computes the mean of a specified MCP feature (mcp) for each combination of sample and cell type,
|
59
|
-
then creates a pairplot to visualize the relationships between these mean MCP values.
|
60
|
-
|
61
|
-
Args:
|
62
|
-
adata: Annotated data object.
|
63
|
-
celltype_key: Key in adata.obs containing cell type annotations.
|
64
|
-
color: Key in adata.obs for color annotations. This parameter is used as the hue
|
65
|
-
sample_id: Key in adata.obs for the sample annotations.
|
66
|
-
mcp: Key in adata.obs for MCP feature values. Defaults to "mcp_0".
|
67
|
-
|
68
|
-
Returns:
|
69
|
-
Seaborn Pairgrid object.
|
70
|
-
|
71
|
-
Examples:
|
72
|
-
>>> import pertpy as pt
|
73
|
-
>>> import scanpy as sc
|
74
|
-
>>> adata = pt.dt.dialogue_example()
|
75
|
-
>>> sc.pp.pca(adata)
|
76
|
-
>>> dl = pt.tl.Dialogue(sample_id = "clinical.status", celltype_key = "cell.subtypes", \
|
77
|
-
n_counts_key = "nCount_RNA", n_mpcs = 3)
|
78
|
-
>>> adata, mcps, ws, ct_subs = dl.calculate_multifactor_PMD(adata, normalize=True)
|
79
|
-
>>> pt.pl.dl.pairplot(adata, celltype_key="cell.subtypes", color="gender", sample_id="clinical.status")
|
80
|
-
"""
|
81
|
-
mean_mcps = adata.obs.groupby([sample_id, celltype_key])[mcp].mean()
|
82
|
-
mean_mcps = mean_mcps.reset_index()
|
83
|
-
mcp_pivot = pd.pivot(mean_mcps[[sample_id, celltype_key, mcp]], index=sample_id, columns=celltype_key)[mcp]
|
84
|
-
|
85
|
-
aggstats = adata.obs.groupby([sample_id])[color].describe()
|
86
|
-
aggstats = aggstats.loc[list(mcp_pivot.index), :]
|
87
|
-
aggstats[color] = aggstats["top"]
|
88
|
-
mcp_pivot = pd.concat([mcp_pivot, aggstats[color]], axis=1)
|
89
|
-
ax = sns.pairplot(mcp_pivot, hue=color, corner=True)
|
90
|
-
|
91
|
-
return ax
|
pertpy/plot/_guide_rna.py
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from typing import TYPE_CHECKING
|
4
|
-
|
5
|
-
import numpy as np
|
6
|
-
import scanpy as sc
|
7
|
-
|
8
|
-
if TYPE_CHECKING:
|
9
|
-
from anndata import AnnData
|
10
|
-
from matplotlib.axes import Axes
|
11
|
-
|
12
|
-
|
13
|
-
class GuideRnaPlot:
|
14
|
-
@staticmethod
|
15
|
-
def heatmap(
|
16
|
-
adata: AnnData,
|
17
|
-
layer: str | None = None,
|
18
|
-
order_by: np.ndarray | str | None = None,
|
19
|
-
key_to_save_order: str = None,
|
20
|
-
**kwds,
|
21
|
-
) -> list[Axes]:
|
22
|
-
"""Heatmap plotting of guide RNA expression matrix.
|
23
|
-
|
24
|
-
Assuming guides have sparse expression, this function reorders cells
|
25
|
-
and plots guide RNA expression so that a nice sparse representation is achieved.
|
26
|
-
The cell ordering can be stored and reused in future plots to obtain consistent
|
27
|
-
plots before and after analysis of the guide RNA expression.
|
28
|
-
Note: This function expects a log-normalized or binary data.
|
29
|
-
|
30
|
-
Args:
|
31
|
-
adata: Annotated data matrix containing gRNA values
|
32
|
-
layer: Key to the layer containing log normalized count values of the gRNAs.
|
33
|
-
adata.X is used if layer is None.
|
34
|
-
order_by: The order of cells in y axis. Defaults to None.
|
35
|
-
If None, cells will be reordered to have a nice sparse representation.
|
36
|
-
If a string is provided, adata.obs[order_by] will be used as the order.
|
37
|
-
If a numpy array is provided, the array will be used for ordering.
|
38
|
-
key_to_save_order: The obs key to save cell orders in the current plot. Only saves if not None.
|
39
|
-
kwds: Are passed to sc.pl.heatmap.
|
40
|
-
|
41
|
-
Returns:
|
42
|
-
List of Axes. Alternatively you can pass save or show parameters as they will be passed to sc.pl.heatmap.
|
43
|
-
Order of cells in the y axis will be saved on adata.obs[key_to_save_order] if provided.
|
44
|
-
|
45
|
-
Examples:
|
46
|
-
Each cell is assigned to gRNA that occurs at least 5 times in the respective cell, which is then
|
47
|
-
visualized using a heatmap.
|
48
|
-
|
49
|
-
>>> import pertpy as pt
|
50
|
-
>>> mdata = pt.data.papalexi_2021()
|
51
|
-
>>> gdo = mdata.mod['gdo']
|
52
|
-
>>> ga = pt.pp.GuideAssignment()
|
53
|
-
>>> ga.assign_by_threshold(gdo, assignment_threshold=5)
|
54
|
-
>>> pt.pl.guide.heatmap(gdo)
|
55
|
-
"""
|
56
|
-
data = adata.X if layer is None else adata.layers[layer]
|
57
|
-
|
58
|
-
if order_by is None:
|
59
|
-
max_guide_index = np.where(
|
60
|
-
np.array(data.max(axis=1)).squeeze() != data.min(), np.array(data.argmax(axis=1)).squeeze(), -1
|
61
|
-
)
|
62
|
-
order = np.argsort(max_guide_index)
|
63
|
-
elif isinstance(order_by, str):
|
64
|
-
order = adata.obs[order_by]
|
65
|
-
else:
|
66
|
-
order = order_by
|
67
|
-
|
68
|
-
adata.obs["_tmp_pertpy_grna_plot_dummy_group"] = ""
|
69
|
-
if key_to_save_order is not None:
|
70
|
-
adata.obs[key_to_save_order] = order
|
71
|
-
axis_group = sc.pl.heatmap(
|
72
|
-
adata[order],
|
73
|
-
adata.var.index.tolist(),
|
74
|
-
groupby="_tmp_pertpy_grna_plot_dummy_group",
|
75
|
-
cmap="viridis",
|
76
|
-
use_raw=False,
|
77
|
-
dendrogram=False,
|
78
|
-
layer=layer,
|
79
|
-
**kwds,
|
80
|
-
)
|
81
|
-
del adata.obs["_tmp_pertpy_grna_plot_dummy_group"]
|
82
|
-
return axis_group
|
pertpy/plot/_milopy.py
DELETED
@@ -1,284 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from typing import TYPE_CHECKING
|
4
|
-
|
5
|
-
import matplotlib.pyplot as plt
|
6
|
-
import numpy as np
|
7
|
-
import pandas as pd
|
8
|
-
import scanpy as sc
|
9
|
-
import seaborn as sns
|
10
|
-
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from collections.abc import Sequence
|
13
|
-
|
14
|
-
from mudata import MuData
|
15
|
-
|
16
|
-
|
17
|
-
class MilopyPlot:
|
18
|
-
"""Plotting functions for Milopy."""
|
19
|
-
|
20
|
-
@staticmethod
|
21
|
-
def nhood_graph(
|
22
|
-
mdata: MuData,
|
23
|
-
alpha: float = 0.1,
|
24
|
-
min_logFC: float = 0,
|
25
|
-
min_size: int = 10,
|
26
|
-
plot_edges: bool = False,
|
27
|
-
title: str = "DA log-Fold Change",
|
28
|
-
show: bool | None = None,
|
29
|
-
save: bool | str | None = None,
|
30
|
-
**kwargs,
|
31
|
-
) -> None:
|
32
|
-
"""Visualize DA results on abstracted graph (wrapper around sc.pl.embedding)
|
33
|
-
|
34
|
-
Args:
|
35
|
-
mdata: MuData object
|
36
|
-
alpha: Significance threshold. (default: 0.1)
|
37
|
-
min_logFC: Minimum absolute log-Fold Change to show results. If is 0, show all significant neighbourhoods. (default: 0)
|
38
|
-
min_size: Minimum size of nodes in visualization. (default: 10)
|
39
|
-
plot_edges: If edges for neighbourhood overlaps whould be plotted. Defaults to False.
|
40
|
-
title: Plot title. Defaults to "DA log-Fold Change".
|
41
|
-
show: Show the plot, do not return axis.
|
42
|
-
save: If `True` or a `str`, save the figure. A string is appended to the default filename.
|
43
|
-
Infer the filetype if ending on {`'.pdf'`, `'.png'`, `'.svg'`}.
|
44
|
-
**kwargs: Additional arguments to `scanpy.pl.embedding`.
|
45
|
-
|
46
|
-
Examples:
|
47
|
-
>>> import pertpy as pt
|
48
|
-
>>> adata = pt.dt.bhattacherjee()
|
49
|
-
>>> milo = pt.tl.Milo()
|
50
|
-
>>> mdata = milo.load(adata)
|
51
|
-
>>> sc.pp.neighbors(mdata["rna"])
|
52
|
-
>>> sc.tl.umap(mdata["rna"])
|
53
|
-
>>> milo.make_nhoods(mdata["rna"])
|
54
|
-
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
55
|
-
>>> milo.da_nhoods(mdata, design="~label")
|
56
|
-
>>> milo.build_nhood_graph(mdata)
|
57
|
-
>>> pt.pl.milo.nhood_graph(mdata)
|
58
|
-
# TODO: If necessary adjust after fixing StopIteration error, which is currently thrown
|
59
|
-
"""
|
60
|
-
nhood_adata = mdata["milo"].T.copy()
|
61
|
-
|
62
|
-
if "Nhood_size" not in nhood_adata.obs.columns:
|
63
|
-
raise KeyError(
|
64
|
-
'Cannot find "Nhood_size" column in adata.uns["nhood_adata"].obs -- \
|
65
|
-
please run milopy.utils.build_nhood_graph(adata)'
|
66
|
-
)
|
67
|
-
|
68
|
-
nhood_adata.obs["graph_color"] = nhood_adata.obs["logFC"]
|
69
|
-
nhood_adata.obs.loc[nhood_adata.obs["SpatialFDR"] > alpha, "graph_color"] = np.nan
|
70
|
-
nhood_adata.obs["abs_logFC"] = abs(nhood_adata.obs["logFC"])
|
71
|
-
nhood_adata.obs.loc[nhood_adata.obs["abs_logFC"] < min_logFC, "graph_color"] = np.nan
|
72
|
-
|
73
|
-
# Plotting order - extreme logFC on top
|
74
|
-
nhood_adata.obs.loc[nhood_adata.obs["graph_color"].isna(), "abs_logFC"] = np.nan
|
75
|
-
ordered = nhood_adata.obs.sort_values("abs_logFC", na_position="first").index
|
76
|
-
nhood_adata = nhood_adata[ordered]
|
77
|
-
|
78
|
-
vmax = np.max([nhood_adata.obs["graph_color"].max(), abs(nhood_adata.obs["graph_color"].min())])
|
79
|
-
vmin = -vmax
|
80
|
-
|
81
|
-
sc.pl.embedding(
|
82
|
-
nhood_adata,
|
83
|
-
"X_milo_graph",
|
84
|
-
color="graph_color",
|
85
|
-
cmap="RdBu_r",
|
86
|
-
size=nhood_adata.obs["Nhood_size"] * min_size,
|
87
|
-
edges=plot_edges,
|
88
|
-
neighbors_key="nhood",
|
89
|
-
sort_order=False,
|
90
|
-
frameon=False,
|
91
|
-
vmax=vmax,
|
92
|
-
vmin=vmin,
|
93
|
-
title=title,
|
94
|
-
show=show,
|
95
|
-
save=save,
|
96
|
-
**kwargs,
|
97
|
-
)
|
98
|
-
|
99
|
-
@staticmethod
|
100
|
-
def nhood(
|
101
|
-
mdata: MuData,
|
102
|
-
ix: int,
|
103
|
-
feature_key: str | None = "rna",
|
104
|
-
basis="X_umap",
|
105
|
-
show: bool | None = None,
|
106
|
-
save: bool | str | None = None,
|
107
|
-
**kwargs,
|
108
|
-
) -> None:
|
109
|
-
"""Visualize cells in a neighbourhood.
|
110
|
-
|
111
|
-
Args:
|
112
|
-
mdata: MuData object with feature_key slot, storing neighbourhood assignments in `mdata[feature_key].obsm['nhoods']`
|
113
|
-
ix: index of neighbourhood to visualize
|
114
|
-
basis: Embedding to use for visualization. Defaults to "X_umap".
|
115
|
-
show: Show the plot, do not return axis.
|
116
|
-
save: If True or a str, save the figure. A string is appended to the default filename. Infer the filetype if ending on {'.pdf', '.png', '.svg'}.
|
117
|
-
**kwargs: Additional arguments to `scanpy.pl.embedding`.
|
118
|
-
|
119
|
-
Examples:
|
120
|
-
>>> import pertpy as pt
|
121
|
-
>>> import scanpy as sc
|
122
|
-
>>> adata = pt.dt.bhattacherjee()
|
123
|
-
>>> milo = pt.tl.Milo()
|
124
|
-
>>> mdata = milo.load(adata)
|
125
|
-
>>> sc.pp.neighbors(mdata["rna"])
|
126
|
-
>>> sc.tl.umap(mdata["rna"])
|
127
|
-
>>> milo.make_nhoods(mdata["rna"])
|
128
|
-
>>> pt.pl.milo.nhood(mdata, ix=0)
|
129
|
-
"""
|
130
|
-
|
131
|
-
mdata[feature_key].obs["Nhood"] = mdata[feature_key].obsm["nhoods"][:, ix].toarray().ravel()
|
132
|
-
sc.pl.embedding(
|
133
|
-
mdata[feature_key], basis, color="Nhood", size=30, title="Nhood" + str(ix), show=show, save=save, **kwargs
|
134
|
-
)
|
135
|
-
|
136
|
-
@staticmethod
|
137
|
-
def da_beeswarm(
|
138
|
-
mdata: MuData,
|
139
|
-
feature_key: str | None = "rna",
|
140
|
-
anno_col: str = "nhood_annotation",
|
141
|
-
alpha: float = 0.1,
|
142
|
-
subset_nhoods: list[str] = None,
|
143
|
-
palette: str | Sequence[str] | dict[str, str] | None = None,
|
144
|
-
):
|
145
|
-
"""Plot beeswarm plot of logFC against nhood labels
|
146
|
-
|
147
|
-
Args:
|
148
|
-
mdata: MuData object
|
149
|
-
anno_col: Column in adata.uns['nhood_adata'].obs to use as annotation. (default: 'nhood_annotation'.)
|
150
|
-
alpha: Significance threshold. (default: 0.1)
|
151
|
-
subset_nhoods: List of nhoods to plot. If None, plot all nhoods. (default: None)
|
152
|
-
palette: Name of Seaborn color palette for violinplots.
|
153
|
-
Defaults to pre-defined category colors for violinplots.
|
154
|
-
|
155
|
-
Examples:
|
156
|
-
>>> import pertpy as pt
|
157
|
-
>>> import scanpy as sc
|
158
|
-
>>> adata = pt.dt.bhattacherjee()
|
159
|
-
>>> milo = pt.tl.Milo()
|
160
|
-
>>> mdata = milo.load(adata)
|
161
|
-
>>> sc.pp.neighbors(mdata["rna"])
|
162
|
-
>>> milo.make_nhoods(mdata["rna"])
|
163
|
-
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
164
|
-
>>> milo.da_nhoods(mdata, design="~label")
|
165
|
-
>>> milo.annotate_nhoods(mdata, anno_col='cell_type')
|
166
|
-
>>> pt.pl.milo.da_beeswarm(mdata)
|
167
|
-
"""
|
168
|
-
try:
|
169
|
-
nhood_adata = mdata["milo"].T.copy()
|
170
|
-
except KeyError:
|
171
|
-
raise RuntimeError(
|
172
|
-
"mdata should be a MuData object with two slots: feature_key and 'milo'. Run 'milopy.count_nhoods(adata)' first."
|
173
|
-
) from None
|
174
|
-
|
175
|
-
if subset_nhoods is not None:
|
176
|
-
nhood_adata = nhood_adata[subset_nhoods]
|
177
|
-
|
178
|
-
try:
|
179
|
-
nhood_adata.obs[anno_col]
|
180
|
-
except KeyError:
|
181
|
-
raise RuntimeError(
|
182
|
-
f"Unable to find {anno_col} in mdata.uns['nhood_adata']. Run 'milopy.utils.annotate_nhoods(adata, anno_col)' first"
|
183
|
-
) from None
|
184
|
-
|
185
|
-
try:
|
186
|
-
nhood_adata.obs["logFC"]
|
187
|
-
except KeyError:
|
188
|
-
raise RuntimeError(
|
189
|
-
"Unable to find 'logFC' in mdata.uns['nhood_adata'].obs. Run 'core.da_nhoods(adata)' first."
|
190
|
-
) from None
|
191
|
-
|
192
|
-
sorted_annos = (
|
193
|
-
nhood_adata.obs[[anno_col, "logFC"]].groupby(anno_col).median().sort_values("logFC", ascending=True).index
|
194
|
-
)
|
195
|
-
|
196
|
-
anno_df = nhood_adata.obs[[anno_col, "logFC", "SpatialFDR"]].copy()
|
197
|
-
anno_df["is_signif"] = anno_df["SpatialFDR"] < alpha
|
198
|
-
anno_df = anno_df[anno_df[anno_col] != "nan"]
|
199
|
-
|
200
|
-
try:
|
201
|
-
obs_col = nhood_adata.uns["annotation_obs"]
|
202
|
-
if palette is None:
|
203
|
-
palette = dict(
|
204
|
-
zip(mdata[feature_key].obs[obs_col].cat.categories, mdata[feature_key].uns[f"{obs_col}_colors"])
|
205
|
-
)
|
206
|
-
sns.violinplot(
|
207
|
-
data=anno_df,
|
208
|
-
y=anno_col,
|
209
|
-
x="logFC",
|
210
|
-
order=sorted_annos,
|
211
|
-
size=190,
|
212
|
-
inner=None,
|
213
|
-
orient="h",
|
214
|
-
palette=palette,
|
215
|
-
linewidth=0,
|
216
|
-
scale="width",
|
217
|
-
)
|
218
|
-
except BaseException: # noqa: BLE001
|
219
|
-
sns.violinplot(
|
220
|
-
data=anno_df,
|
221
|
-
y=anno_col,
|
222
|
-
x="logFC",
|
223
|
-
order=sorted_annos,
|
224
|
-
size=190,
|
225
|
-
inner=None,
|
226
|
-
orient="h",
|
227
|
-
linewidth=0,
|
228
|
-
scale="width",
|
229
|
-
)
|
230
|
-
sns.stripplot(
|
231
|
-
data=anno_df,
|
232
|
-
y=anno_col,
|
233
|
-
x="logFC",
|
234
|
-
order=sorted_annos,
|
235
|
-
size=2,
|
236
|
-
hue="is_signif",
|
237
|
-
palette=["grey", "black"],
|
238
|
-
orient="h",
|
239
|
-
alpha=0.5,
|
240
|
-
)
|
241
|
-
plt.legend(loc="upper left", title=f"< {int(alpha * 100)}% SpatialFDR", bbox_to_anchor=(1, 1), frameon=False)
|
242
|
-
plt.axvline(x=0, ymin=0, ymax=1, color="black", linestyle="--")
|
243
|
-
|
244
|
-
@staticmethod
|
245
|
-
def nhood_counts_by_cond(
|
246
|
-
mdata: MuData,
|
247
|
-
test_var: str,
|
248
|
-
subset_nhoods: list = None,
|
249
|
-
log_counts: bool = False,
|
250
|
-
):
|
251
|
-
"""Plot boxplot of cell numbers vs condition of interest
|
252
|
-
|
253
|
-
Args:
|
254
|
-
mdata: MuData object storing cell level and nhood level information
|
255
|
-
test_var: Name of column in adata.obs storing condition of interest (y-axis for boxplot)
|
256
|
-
subset_nhoods: List of obs_names for neighbourhoods to include in plot. If None, plot all nhoods. (default: None)
|
257
|
-
log_counts: Whether to plot log1p of cell counts. (default: False)
|
258
|
-
"""
|
259
|
-
try:
|
260
|
-
nhood_adata = mdata["milo"].T.copy()
|
261
|
-
except KeyError:
|
262
|
-
raise RuntimeError(
|
263
|
-
"mdata should be a MuData object with two slots: feature_key and 'milo'. Run milopy.count_nhoods(mdata) first"
|
264
|
-
) from None
|
265
|
-
|
266
|
-
if subset_nhoods is None:
|
267
|
-
subset_nhoods = nhood_adata.obs_names
|
268
|
-
|
269
|
-
pl_df = pd.DataFrame(nhood_adata[subset_nhoods].X.A, columns=nhood_adata.var_names).melt(
|
270
|
-
var_name=nhood_adata.uns["sample_col"], value_name="n_cells"
|
271
|
-
)
|
272
|
-
pl_df = pd.merge(pl_df, nhood_adata.var)
|
273
|
-
pl_df["log_n_cells"] = np.log1p(pl_df["n_cells"])
|
274
|
-
if not log_counts:
|
275
|
-
sns.boxplot(data=pl_df, x=test_var, y="n_cells", color="lightblue")
|
276
|
-
sns.stripplot(data=pl_df, x=test_var, y="n_cells", color="black", s=3)
|
277
|
-
plt.ylabel("# cells")
|
278
|
-
else:
|
279
|
-
sns.boxplot(data=pl_df, x=test_var, y="log_n_cells", color="lightblue")
|
280
|
-
sns.stripplot(data=pl_df, x=test_var, y="log_n_cells", color="black", s=3)
|
281
|
-
plt.ylabel("log(# cells + 1)")
|
282
|
-
|
283
|
-
plt.xticks(rotation=90)
|
284
|
-
plt.xlabel(test_var)
|