pertpy 0.10.0__py3-none-any.whl → 0.11.1__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 +5 -1
- pertpy/_doc.py +1 -3
- pertpy/_types.py +6 -0
- pertpy/data/_dataloader.py +68 -24
- pertpy/data/_datasets.py +9 -9
- pertpy/metadata/__init__.py +2 -1
- pertpy/metadata/_cell_line.py +133 -25
- pertpy/metadata/_look_up.py +13 -19
- pertpy/metadata/_moa.py +1 -1
- pertpy/preprocessing/_guide_rna.py +138 -44
- pertpy/preprocessing/_guide_rna_mixture.py +17 -19
- pertpy/tools/__init__.py +4 -3
- pertpy/tools/_augur.py +106 -98
- pertpy/tools/_cinemaot.py +74 -114
- pertpy/tools/_coda/_base_coda.py +134 -148
- pertpy/tools/_coda/_sccoda.py +69 -70
- pertpy/tools/_coda/_tasccoda.py +74 -80
- pertpy/tools/_dialogue.py +48 -41
- pertpy/tools/_differential_gene_expression/_base.py +21 -31
- pertpy/tools/_differential_gene_expression/_checks.py +4 -6
- pertpy/tools/_differential_gene_expression/_dge_comparison.py +5 -6
- pertpy/tools/_differential_gene_expression/_edger.py +6 -10
- pertpy/tools/_differential_gene_expression/_pydeseq2.py +1 -1
- pertpy/tools/_differential_gene_expression/_simple_tests.py +3 -3
- pertpy/tools/_differential_gene_expression/_statsmodels.py +8 -5
- pertpy/tools/_distances/_distance_tests.py +1 -2
- pertpy/tools/_distances/_distances.py +31 -46
- pertpy/tools/_enrichment.py +7 -22
- pertpy/tools/_milo.py +19 -15
- pertpy/tools/_mixscape.py +73 -75
- pertpy/tools/_perturbation_space/_clustering.py +4 -4
- pertpy/tools/_perturbation_space/_comparison.py +4 -4
- pertpy/tools/_perturbation_space/_discriminator_classifiers.py +83 -32
- pertpy/tools/_perturbation_space/_perturbation_space.py +10 -10
- pertpy/tools/_perturbation_space/_simple.py +12 -14
- pertpy/tools/_scgen/_scgen.py +16 -17
- pertpy/tools/_scgen/_scgenvae.py +2 -2
- pertpy/tools/_scgen/_utils.py +3 -1
- {pertpy-0.10.0.dist-info → pertpy-0.11.1.dist-info}/METADATA +42 -24
- pertpy-0.11.1.dist-info/RECORD +58 -0
- {pertpy-0.10.0.dist-info → pertpy-0.11.1.dist-info}/licenses/LICENSE +1 -0
- pertpy/tools/_kernel_pca.py +0 -50
- pertpy-0.10.0.dist-info/RECORD +0 -58
- {pertpy-0.10.0.dist-info → pertpy-0.11.1.dist-info}/WHEEL +0 -0
@@ -1,12 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import multiprocessing
|
4
3
|
from abc import ABC, abstractmethod
|
5
4
|
from typing import TYPE_CHECKING, Literal, NamedTuple
|
6
5
|
|
7
|
-
import numba
|
8
6
|
import numpy as np
|
9
7
|
import pandas as pd
|
8
|
+
from numba import jit
|
10
9
|
from ott.geometry.geometry import Geometry
|
11
10
|
from ott.geometry.pointcloud import PointCloud
|
12
11
|
from ott.problems.linear.linear_problem import LinearProblem
|
@@ -135,9 +134,7 @@ class Distance:
|
|
135
134
|
self.aggregation_func = agg_fct
|
136
135
|
if metric == "edistance":
|
137
136
|
metric_fct = Edistance()
|
138
|
-
elif metric
|
139
|
-
metric_fct = EuclideanDistance(self.aggregation_func)
|
140
|
-
elif metric == "root_mean_squared_error":
|
137
|
+
elif metric in ("euclidean", "root_mean_squared_error"):
|
141
138
|
metric_fct = EuclideanDistance(self.aggregation_func)
|
142
139
|
elif metric == "mse":
|
143
140
|
metric_fct = MeanSquaredDistance(self.aggregation_func)
|
@@ -181,7 +178,7 @@ class Distance:
|
|
181
178
|
|
182
179
|
if layer_key and obsm_key:
|
183
180
|
raise ValueError(
|
184
|
-
"Cannot use 'layer_key' and 'obsm_key' at the same time.\
|
181
|
+
"Cannot use 'layer_key' and 'obsm_key' at the same time.\nPlease provide only one of the two keys."
|
185
182
|
)
|
186
183
|
if not layer_key and not obsm_key:
|
187
184
|
obsm_key = "X_pca"
|
@@ -201,6 +198,7 @@ class Distance:
|
|
201
198
|
Args:
|
202
199
|
X: First vector of shape (n_samples, n_features).
|
203
200
|
Y: Second vector of shape (n_samples, n_features).
|
201
|
+
kwargs: Passed to the metric function.
|
204
202
|
|
205
203
|
Returns:
|
206
204
|
float: Distance between X and Y.
|
@@ -239,9 +237,10 @@ class Distance:
|
|
239
237
|
Y: Second vector of shape (n_samples, n_features).
|
240
238
|
n_bootstrap: Number of bootstrap samples.
|
241
239
|
random_state: Random state for bootstrapping.
|
240
|
+
**kwargs: Passed to the metric function.
|
242
241
|
|
243
242
|
Returns:
|
244
|
-
|
243
|
+
Mean and variance of distance between X and Y.
|
245
244
|
|
246
245
|
Examples:
|
247
246
|
>>> import pertpy as pt
|
@@ -286,8 +285,8 @@ class Distance:
|
|
286
285
|
kwargs: Additional keyword arguments passed to the metric function.
|
287
286
|
|
288
287
|
Returns:
|
289
|
-
|
290
|
-
tuple[
|
288
|
+
:class:`pandas.DataFrame`: Dataframe with pairwise distances.
|
289
|
+
tuple[:class:`pandas.DataFrame`, :class:`pandas.DataFrame`]: Two Dataframes, one for the mean and one for the variance of pairwise distances.
|
291
290
|
|
292
291
|
Examples:
|
293
292
|
>>> import pertpy as pt
|
@@ -309,7 +308,7 @@ class Distance:
|
|
309
308
|
# able to handle precomputed distances such as the PseudobulkDistance.
|
310
309
|
if self.metric_fct.accepts_precomputed:
|
311
310
|
# Precompute the pairwise distances if needed
|
312
|
-
if f"{self.obsm_key}_{self.cell_wise_metric}_predistances" not in adata.obsp
|
311
|
+
if f"{self.obsm_key}_{self.cell_wise_metric}_predistances" not in adata.obsp:
|
313
312
|
self.precompute_distances(adata, n_jobs=n_jobs, **kwargs)
|
314
313
|
pwd = adata.obsp[f"{self.obsm_key}_{self.cell_wise_metric}_predistances"]
|
315
314
|
for index_x, group_x in enumerate(fct(groups)):
|
@@ -339,10 +338,7 @@ class Distance:
|
|
339
338
|
df.loc[group_x, group_y] = df.loc[group_y, group_x] = bootstrap_output.mean
|
340
339
|
df_var.loc[group_x, group_y] = df_var.loc[group_y, group_x] = bootstrap_output.variance
|
341
340
|
else:
|
342
|
-
if self.layer_key
|
343
|
-
embedding = adata.layers[self.layer_key]
|
344
|
-
else:
|
345
|
-
embedding = adata.obsm[self.obsm_key].copy()
|
341
|
+
embedding = adata.layers[self.layer_key] if self.layer_key else adata.obsm[self.obsm_key].copy()
|
346
342
|
for index_x, group_x in enumerate(fct(groups)):
|
347
343
|
cells_x = embedding[np.asarray(grouping == group_x)].copy()
|
348
344
|
for group_y in groups[index_x:]: # type: ignore
|
@@ -409,8 +405,8 @@ class Distance:
|
|
409
405
|
kwargs: Additional keyword arguments passed to the metric function.
|
410
406
|
|
411
407
|
Returns:
|
412
|
-
|
413
|
-
tuple[
|
408
|
+
:class:`pandas.DataFrame`: Dataframe with distances of groups to selected_group.
|
409
|
+
tuple[:class:`pandas.DataFrame`, :class:`pandas.DataFrame`]: Two Dataframes, one for the mean and one for the variance of distances of groups to selected_group.
|
414
410
|
|
415
411
|
|
416
412
|
Examples:
|
@@ -446,7 +442,7 @@ class Distance:
|
|
446
442
|
# able to handle precomputed distances such as the PseudobulkDistance.
|
447
443
|
if self.metric_fct.accepts_precomputed:
|
448
444
|
# Precompute the pairwise distances if needed
|
449
|
-
if f"{self.obsm_key}_{self.cell_wise_metric}_predistances" not in adata.obsp
|
445
|
+
if f"{self.obsm_key}_{self.cell_wise_metric}_predistances" not in adata.obsp:
|
450
446
|
self.precompute_distances(adata, n_jobs=n_jobs, **kwargs)
|
451
447
|
pwd = adata.obsp[f"{self.obsm_key}_{self.cell_wise_metric}_predistances"]
|
452
448
|
for group_x in fct(groups):
|
@@ -473,10 +469,7 @@ class Distance:
|
|
473
469
|
df.loc[group_x] = bootstrap_output.mean
|
474
470
|
df_var.loc[group_x] = bootstrap_output.variance
|
475
471
|
else:
|
476
|
-
if self.layer_key
|
477
|
-
embedding = adata.layers[self.layer_key]
|
478
|
-
else:
|
479
|
-
embedding = adata.obsm[self.obsm_key].copy()
|
472
|
+
embedding = adata.layers[self.layer_key] if self.layer_key else adata.obsm[self.obsm_key].copy()
|
480
473
|
for group_x in fct(groups):
|
481
474
|
cells_x = embedding[np.asarray(grouping == group_x)].copy()
|
482
475
|
group_y = selected_group
|
@@ -524,10 +517,7 @@ class Distance:
|
|
524
517
|
>>> distance = pt.tools.Distance(metric="edistance")
|
525
518
|
>>> distance.precompute_distances(adata)
|
526
519
|
"""
|
527
|
-
if self.layer_key
|
528
|
-
cells = adata.layers[self.layer_key]
|
529
|
-
else:
|
530
|
-
cells = adata.obsm[self.obsm_key].copy()
|
520
|
+
cells = adata.layers[self.layer_key] if self.layer_key else adata.obsm[self.obsm_key].copy()
|
531
521
|
pwd = pairwise_distances(cells, cells, metric=self.cell_wise_metric, n_jobs=n_jobs)
|
532
522
|
adata.obsp[f"{self.obsm_key}_{self.cell_wise_metric}_predistances"] = pwd
|
533
523
|
|
@@ -618,6 +608,7 @@ class AbstractDistance(ABC):
|
|
618
608
|
Args:
|
619
609
|
X: First vector of shape (n_samples, n_features).
|
620
610
|
Y: Second vector of shape (n_samples, n_features).
|
611
|
+
kwargs: Passed to the metrics function.
|
621
612
|
|
622
613
|
Returns:
|
623
614
|
float: Distance between X and Y.
|
@@ -630,8 +621,8 @@ class AbstractDistance(ABC):
|
|
630
621
|
|
631
622
|
Args:
|
632
623
|
P: Pairwise distance matrix of shape (n_samples, n_samples).
|
633
|
-
idx: Boolean array of shape (n_samples,) indicating which
|
634
|
-
|
624
|
+
idx: Boolean array of shape (n_samples,) indicating which samples belong to X (or Y, since each metric is symmetric).
|
625
|
+
kwargs: Passed to the metrics function.
|
635
626
|
|
636
627
|
Returns:
|
637
628
|
float: Distance between X and Y.
|
@@ -645,12 +636,12 @@ class Edistance(AbstractDistance):
|
|
645
636
|
def __init__(self) -> None:
|
646
637
|
super().__init__()
|
647
638
|
self.accepts_precomputed = True
|
648
|
-
self.cell_wise_metric = "
|
639
|
+
self.cell_wise_metric = "euclidean"
|
649
640
|
|
650
641
|
def __call__(self, X: np.ndarray, Y: np.ndarray, **kwargs) -> float:
|
651
|
-
sigma_X = pairwise_distances(X, X, metric=
|
652
|
-
sigma_Y = pairwise_distances(Y, Y, metric=
|
653
|
-
delta = pairwise_distances(X, Y, metric=
|
642
|
+
sigma_X = pairwise_distances(X, X, metric=self.cell_wise_metric, **kwargs).mean()
|
643
|
+
sigma_Y = pairwise_distances(Y, Y, metric=self.cell_wise_metric, **kwargs).mean()
|
644
|
+
delta = pairwise_distances(X, Y, metric=self.cell_wise_metric, **kwargs).mean()
|
654
645
|
return 2 * delta - sigma_X - sigma_Y
|
655
646
|
|
656
647
|
def from_precomputed(self, P: np.ndarray, idx: np.ndarray, **kwargs) -> float:
|
@@ -881,7 +872,7 @@ class R2ScoreDistance(AbstractDistance):
|
|
881
872
|
|
882
873
|
|
883
874
|
class SymmetricKLDivergence(AbstractDistance):
|
884
|
-
"""Average of symmetric KL divergence between gene distributions of two groups
|
875
|
+
"""Average of symmetric KL divergence between gene distributions of two groups.
|
885
876
|
|
886
877
|
Assuming a Gaussian distribution for each gene in each group, calculates
|
887
878
|
the KL divergence between them and averages over all genes. Repeats this ABBA to get a symmetrized distance.
|
@@ -908,7 +899,7 @@ class SymmetricKLDivergence(AbstractDistance):
|
|
908
899
|
|
909
900
|
|
910
901
|
class TTestDistance(AbstractDistance):
|
911
|
-
"""Average of T test statistic between two groups assuming unequal variances"""
|
902
|
+
"""Average of T test statistic between two groups assuming unequal variances."""
|
912
903
|
|
913
904
|
def __init__(self) -> None:
|
914
905
|
super().__init__()
|
@@ -932,16 +923,14 @@ class TTestDistance(AbstractDistance):
|
|
932
923
|
|
933
924
|
|
934
925
|
class KSTestDistance(AbstractDistance):
|
935
|
-
"""Average of two-sided KS test statistic between two groups"""
|
926
|
+
"""Average of two-sided KS test statistic between two groups."""
|
936
927
|
|
937
928
|
def __init__(self) -> None:
|
938
929
|
super().__init__()
|
939
930
|
self.accepts_precomputed = False
|
940
931
|
|
941
932
|
def __call__(self, X: np.ndarray, Y: np.ndarray, **kwargs) -> float:
|
942
|
-
stats = []
|
943
|
-
for i in range(X.shape[1]):
|
944
|
-
stats.append(abs(kstest(X[:, i], Y[:, i])[0]))
|
933
|
+
stats = [abs(kstest(X[:, i], Y[:, i])[0]) for i in range(X.shape[1])]
|
945
934
|
return sum(stats) / len(stats)
|
946
935
|
|
947
936
|
def from_precomputed(self, P: np.ndarray, idx: np.ndarray, **kwargs) -> float:
|
@@ -949,10 +938,7 @@ class KSTestDistance(AbstractDistance):
|
|
949
938
|
|
950
939
|
|
951
940
|
class NBLL(AbstractDistance):
|
952
|
-
"""
|
953
|
-
Average of Log likelihood (scalar) of group B cells
|
954
|
-
according to a NB distribution fitted over group A
|
955
|
-
"""
|
941
|
+
"""Average of Log likelihood (scalar) of group B cells according to a NB distribution fitted over group A."""
|
956
942
|
|
957
943
|
def __init__(self) -> None:
|
958
944
|
super().__init__()
|
@@ -960,15 +946,12 @@ class NBLL(AbstractDistance):
|
|
960
946
|
|
961
947
|
def __call__(self, X: np.ndarray, Y: np.ndarray, epsilon=1e-8, **kwargs) -> float:
|
962
948
|
def _is_count_matrix(matrix, tolerance=1e-6):
|
963
|
-
|
964
|
-
return True
|
965
|
-
else:
|
966
|
-
return False
|
949
|
+
return bool(matrix.dtype.kind == "i" or np.all(np.abs(matrix - np.round(matrix)) < tolerance))
|
967
950
|
|
968
951
|
if not _is_count_matrix(matrix=X) or not _is_count_matrix(matrix=Y):
|
969
952
|
raise ValueError("NBLL distance only works for raw counts.")
|
970
953
|
|
971
|
-
@
|
954
|
+
@jit(forceobj=True)
|
972
955
|
def _compute_nll(y: np.ndarray, nb_params: tuple[float, float], epsilon: float) -> float:
|
973
956
|
mu = np.exp(nb_params[0])
|
974
957
|
theta = 1 / nb_params[1]
|
@@ -1163,9 +1146,11 @@ class MeanVarDistributionDistance(AbstractDistance):
|
|
1163
1146
|
|
1164
1147
|
def __call__(self, X: np.ndarray, Y: np.ndarray, **kwargs) -> float:
|
1165
1148
|
"""Difference of mean-var distributions in 2 matrices.
|
1149
|
+
|
1166
1150
|
Args:
|
1167
1151
|
X: Normalized and log transformed cells x genes count matrix.
|
1168
1152
|
Y: Normalized and log transformed cells x genes count matrix.
|
1153
|
+
kwargs: Passed to the metrics function.
|
1169
1154
|
"""
|
1170
1155
|
mean_x, var_x = self._mean_var(X, log=True)
|
1171
1156
|
mean_y, var_y = self._mean_var(Y, log=True)
|
pertpy/tools/_enrichment.py
CHANGED
@@ -25,10 +25,7 @@ def _prepare_targets(
|
|
25
25
|
categories: str | Sequence[str] = None,
|
26
26
|
) -> ChainMap | dict:
|
27
27
|
if categories is not None:
|
28
|
-
if isinstance(categories, str)
|
29
|
-
categories = [categories]
|
30
|
-
else:
|
31
|
-
categories = list(categories)
|
28
|
+
categories = [categories] if isinstance(categories, str) else list(categories)
|
32
29
|
|
33
30
|
if targets is None:
|
34
31
|
pt_drug = Drug()
|
@@ -97,10 +94,7 @@ class Enrichment:
|
|
97
94
|
Returns:
|
98
95
|
An AnnData object with scores.
|
99
96
|
"""
|
100
|
-
if layer is not None
|
101
|
-
mtx = adata.layers[layer]
|
102
|
-
else:
|
103
|
-
mtx = adata.X
|
97
|
+
mtx = adata.layers[layer] if layer is not None else adata.X
|
104
98
|
|
105
99
|
targets = _prepare_targets(targets=targets, nested=nested, categories=categories) # type: ignore
|
106
100
|
full_targets = targets.copy()
|
@@ -114,10 +108,7 @@ class Enrichment:
|
|
114
108
|
weights = pd.DataFrame(targets, index=adata.var_names)
|
115
109
|
weights = weights.loc[:, weights.sum() > 0]
|
116
110
|
weights = weights / weights.sum()
|
117
|
-
if issparse(mtx)
|
118
|
-
scores = mtx.dot(weights)
|
119
|
-
else:
|
120
|
-
scores = np.dot(mtx, weights)
|
111
|
+
scores = mtx.dot(weights) if issparse(mtx) else np.dot(mtx, weights)
|
121
112
|
|
122
113
|
if method == "seurat":
|
123
114
|
obs_avg = _mean(mtx, names=adata.var_names, axis=0)
|
@@ -136,10 +127,7 @@ class Enrichment:
|
|
136
127
|
control_gene_weights = pd.DataFrame(control_groups, index=adata.var_names)
|
137
128
|
control_gene_weights = control_gene_weights / control_gene_weights.sum()
|
138
129
|
|
139
|
-
if issparse(mtx)
|
140
|
-
control_profiles = mtx.dot(control_gene_weights)
|
141
|
-
else:
|
142
|
-
control_profiles = np.dot(mtx, control_gene_weights)
|
130
|
+
control_profiles = mtx.dot(control_gene_weights) if issparse(mtx) else np.dot(mtx, control_gene_weights)
|
143
131
|
drug_bins = {}
|
144
132
|
for drug in weights.columns:
|
145
133
|
bins = np.unique(obs_cut[targets[drug]])
|
@@ -178,7 +166,7 @@ class Enrichment:
|
|
178
166
|
Accepts two forms:
|
179
167
|
- A dictionary with the names of the groups as keys, and the entries being the corresponding gene lists.
|
180
168
|
- A dictionary of dictionaries defined like above, with names of gene group categories as keys.
|
181
|
-
|
169
|
+
If passing one of those, specify `nested=True`.
|
182
170
|
nested: Whether `targets` is a dictionary of dictionaries with group categories as keys.
|
183
171
|
categories: If `targets=None` or `nested=True`, this argument can be used to subset the gene groups to one or more categories (keys of the original dictionary).
|
184
172
|
In case of the ChEMBL drug targets, these are ATC level 1/level 2 category codes.
|
@@ -293,7 +281,7 @@ class Enrichment:
|
|
293
281
|
return enrichment
|
294
282
|
|
295
283
|
@_doc_params(common_plot_args=doc_common_plot_args)
|
296
|
-
def plot_dotplot(
|
284
|
+
def plot_dotplot( # pragma: no cover # noqa: D417
|
297
285
|
self,
|
298
286
|
adata: AnnData,
|
299
287
|
*,
|
@@ -341,10 +329,7 @@ class Enrichment:
|
|
341
329
|
.. image:: /_static/docstring_previews/enrichment_dotplot.png
|
342
330
|
"""
|
343
331
|
if categories is not None:
|
344
|
-
if isinstance(categories, str)
|
345
|
-
categories = [categories]
|
346
|
-
else:
|
347
|
-
categories = list(categories)
|
332
|
+
categories = [categories] if isinstance(categories, str) else list(categories)
|
348
333
|
|
349
334
|
if targets is None:
|
350
335
|
pt_drug = Drug()
|
pertpy/tools/_milo.py
CHANGED
@@ -51,14 +51,16 @@ class Milo:
|
|
51
51
|
Args:
|
52
52
|
input: AnnData
|
53
53
|
feature_key: Key to store the cell-level AnnData object in the MuData object
|
54
|
+
|
54
55
|
Returns:
|
55
|
-
|
56
|
+
:class:`mudata.MuData` object with original AnnData.
|
56
57
|
|
57
58
|
Examples:
|
58
59
|
>>> import pertpy as pt
|
59
60
|
>>> adata = pt.dt.bhattacherjee()
|
60
61
|
>>> milo = pt.tl.Milo()
|
61
62
|
>>> mdata = milo.load(adata)
|
63
|
+
|
62
64
|
"""
|
63
65
|
mdata = MuData({feature_key: input, "milo": AnnData()})
|
64
66
|
|
@@ -113,6 +115,7 @@ class Milo:
|
|
113
115
|
>>> mdata = milo.load(adata)
|
114
116
|
>>> sc.pp.neighbors(mdata["rna"])
|
115
117
|
>>> milo.make_nhoods(mdata["rna"])
|
118
|
+
|
116
119
|
"""
|
117
120
|
if isinstance(data, MuData):
|
118
121
|
adata = data[feature_key]
|
@@ -177,10 +180,7 @@ class Milo:
|
|
177
180
|
adata.obs["nhood_ixs_random"] = adata.obs["nhood_ixs_random"].astype("int")
|
178
181
|
adata.uns["nhood_neighbors_key"] = neighbors_key
|
179
182
|
# Store distance to K-th nearest neighbor (used for spatial FDR correction)
|
180
|
-
if neighbors_key is None
|
181
|
-
knn_dists = adata.obsp["distances"]
|
182
|
-
else:
|
183
|
-
knn_dists = adata.obsp[neighbors_key + "_distances"]
|
183
|
+
knn_dists = adata.obsp["distances"] if neighbors_key is None else adata.obsp[neighbors_key + "_distances"]
|
184
184
|
|
185
185
|
nhood_ixs = adata.obs["nhood_ixs_refined"] == 1
|
186
186
|
dist_mat = knn_dists[np.asarray(nhood_ixs), :]
|
@@ -223,6 +223,7 @@ class Milo:
|
|
223
223
|
>>> sc.pp.neighbors(mdata["rna"])
|
224
224
|
>>> milo.make_nhoods(mdata["rna"])
|
225
225
|
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
226
|
+
|
226
227
|
"""
|
227
228
|
if isinstance(data, MuData):
|
228
229
|
adata = data[feature_key]
|
@@ -297,6 +298,7 @@ class Milo:
|
|
297
298
|
>>> milo.make_nhoods(mdata["rna"])
|
298
299
|
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
299
300
|
>>> milo.da_nhoods(mdata, design="~label")
|
301
|
+
|
300
302
|
"""
|
301
303
|
try:
|
302
304
|
sample_adata = mdata["milo"]
|
@@ -428,7 +430,7 @@ class Milo:
|
|
428
430
|
feature_key: If input data is MuData, specify key to cell-level AnnData object.
|
429
431
|
|
430
432
|
Returns:
|
431
|
-
|
433
|
+
Adds in place.
|
432
434
|
- `milo_mdata['milo'].var["nhood_annotation"]`: assigning a label to each nhood
|
433
435
|
- `milo_mdata['milo'].var["nhood_annotation_frac"]` stores the fraciton of cells in the neighbourhood with the assigned label
|
434
436
|
- `milo_mdata['milo'].varm['frac_annotation']`: stores the fraction of cells from each label in each nhood
|
@@ -444,6 +446,7 @@ class Milo:
|
|
444
446
|
>>> milo.make_nhoods(mdata["rna"])
|
445
447
|
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
446
448
|
>>> milo.annotate_nhoods(mdata, anno_col="cell_type")
|
449
|
+
|
447
450
|
"""
|
448
451
|
try:
|
449
452
|
sample_adata = mdata["milo"]
|
@@ -482,7 +485,7 @@ class Milo:
|
|
482
485
|
feature_key: If input data is MuData, specify key to cell-level AnnData object.
|
483
486
|
|
484
487
|
Returns:
|
485
|
-
|
488
|
+
Adds in place.
|
486
489
|
- `milo_mdata['milo'].var["nhood_{anno_col}"]`: assigning a continuous value to each nhood
|
487
490
|
|
488
491
|
Examples:
|
@@ -567,7 +570,7 @@ class Milo:
|
|
567
570
|
sample_adata.obs = sample_obs.loc[sample_adata.obs_names]
|
568
571
|
|
569
572
|
def build_nhood_graph(self, mdata: MuData, basis: str = "X_umap", feature_key: str | None = "rna"):
|
570
|
-
"""Build graph of neighbourhoods used for visualization of DA results
|
573
|
+
"""Build graph of neighbourhoods used for visualization of DA results.
|
571
574
|
|
572
575
|
Args:
|
573
576
|
mdata: MuData object
|
@@ -625,6 +628,7 @@ class Milo:
|
|
625
628
|
>>> milo.make_nhoods(mdata["rna"])
|
626
629
|
>>> mdata = milo.count_nhoods(mdata, sample_col="orig.ident")
|
627
630
|
>>> milo.add_nhood_expression(mdata)
|
631
|
+
|
628
632
|
"""
|
629
633
|
try:
|
630
634
|
sample_adata = mdata["milo"]
|
@@ -652,7 +656,7 @@ class Milo:
|
|
652
656
|
def _setup_rpy2(
|
653
657
|
self,
|
654
658
|
):
|
655
|
-
"""Set up rpy2 to run edgeR"""
|
659
|
+
"""Set up rpy2 to run edgeR."""
|
656
660
|
from rpy2.robjects import numpy2ri, pandas2ri
|
657
661
|
from rpy2.robjects.packages import importr
|
658
662
|
|
@@ -715,7 +719,7 @@ class Milo:
|
|
715
719
|
sample_adata.var.loc[keep_nhoods, "SpatialFDR"] = adjp
|
716
720
|
|
717
721
|
@_doc_params(common_plot_args=doc_common_plot_args)
|
718
|
-
def plot_nhood_graph(
|
722
|
+
def plot_nhood_graph( # pragma: no cover # noqa: D417
|
719
723
|
self,
|
720
724
|
mdata: MuData,
|
721
725
|
*,
|
@@ -730,7 +734,7 @@ class Milo:
|
|
730
734
|
return_fig: bool = False,
|
731
735
|
**kwargs,
|
732
736
|
) -> Figure | None:
|
733
|
-
"""Visualize DA results on abstracted graph (wrapper around sc.pl.embedding)
|
737
|
+
"""Visualize DA results on abstracted graph (wrapper around sc.pl.embedding).
|
734
738
|
|
735
739
|
Args:
|
736
740
|
mdata: MuData object
|
@@ -808,7 +812,7 @@ class Milo:
|
|
808
812
|
return None
|
809
813
|
|
810
814
|
@_doc_params(common_plot_args=doc_common_plot_args)
|
811
|
-
def plot_nhood(
|
815
|
+
def plot_nhood( # pragma: no cover # noqa: D417
|
812
816
|
self,
|
813
817
|
mdata: MuData,
|
814
818
|
ix: int,
|
@@ -869,7 +873,7 @@ class Milo:
|
|
869
873
|
return None
|
870
874
|
|
871
875
|
@_doc_params(common_plot_args=doc_common_plot_args)
|
872
|
-
def plot_da_beeswarm(
|
876
|
+
def plot_da_beeswarm( # pragma: no cover # noqa: D417
|
873
877
|
self,
|
874
878
|
mdata: MuData,
|
875
879
|
*,
|
@@ -880,7 +884,7 @@ class Milo:
|
|
880
884
|
palette: str | Sequence[str] | dict[str, str] | None = None,
|
881
885
|
return_fig: bool = False,
|
882
886
|
) -> Figure | None:
|
883
|
-
"""Plot beeswarm plot of logFC against nhood labels
|
887
|
+
"""Plot beeswarm plot of logFC against nhood labels.
|
884
888
|
|
885
889
|
Args:
|
886
890
|
mdata: MuData object
|
@@ -995,7 +999,7 @@ class Milo:
|
|
995
999
|
return None
|
996
1000
|
|
997
1001
|
@_doc_params(common_plot_args=doc_common_plot_args)
|
998
|
-
def plot_nhood_counts_by_cond(
|
1002
|
+
def plot_nhood_counts_by_cond( # pragma: no cover # noqa: D417
|
999
1003
|
self,
|
1000
1004
|
mdata: MuData,
|
1001
1005
|
test_var: str,
|