pertpy 0.11.4__py3-none-any.whl → 0.11.5__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 +1 -1
- pertpy/tools/_coda/_base_coda.py +1 -1
- pertpy/tools/_distances/_distances.py +3 -2
- pertpy/tools/_milo.py +63 -29
- pertpy/tools/_mixscape.py +42 -39
- pertpy/tools/_perturbation_space/_discriminator_classifiers.py +1 -1
- pertpy/tools/_scgen/_scgen.py +2 -1
- {pertpy-0.11.4.dist-info → pertpy-0.11.5.dist-info}/METADATA +8 -1
- {pertpy-0.11.4.dist-info → pertpy-0.11.5.dist-info}/RECORD +11 -11
- {pertpy-0.11.4.dist-info → pertpy-0.11.5.dist-info}/WHEEL +0 -0
- {pertpy-0.11.4.dist-info → pertpy-0.11.5.dist-info}/licenses/LICENSE +0 -0
pertpy/__init__.py
CHANGED
pertpy/tools/_coda/_base_coda.py
CHANGED
@@ -1538,7 +1538,7 @@ class CompositionalModel2(ABC):
|
|
1538
1538
|
if isinstance(data, MuData):
|
1539
1539
|
data = data[modality_key]
|
1540
1540
|
if isinstance(palette, Colormap):
|
1541
|
-
palette = palette(range(
|
1541
|
+
palette = list(palette(range(len(data.obs[feature_name].unique()))))
|
1542
1542
|
|
1543
1543
|
# y scale transformations
|
1544
1544
|
if y_scale == "relative":
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
3
3
|
from abc import ABC, abstractmethod
|
4
4
|
from typing import TYPE_CHECKING, Literal, NamedTuple
|
5
5
|
|
6
|
+
import jax
|
6
7
|
import numpy as np
|
7
8
|
import pandas as pd
|
8
9
|
from numba import jit
|
@@ -685,6 +686,7 @@ class WassersteinDistance(AbstractDistance):
|
|
685
686
|
def __init__(self) -> None:
|
686
687
|
super().__init__()
|
687
688
|
self.accepts_precomputed = False
|
689
|
+
self.solver = jax.jit(Sinkhorn())
|
688
690
|
|
689
691
|
def __call__(self, X: np.ndarray, Y: np.ndarray, **kwargs) -> float:
|
690
692
|
X = np.asarray(X, dtype=np.float64)
|
@@ -699,8 +701,7 @@ class WassersteinDistance(AbstractDistance):
|
|
699
701
|
|
700
702
|
def solve_ot_problem(self, geom: Geometry, **kwargs):
|
701
703
|
ot_prob = LinearProblem(geom)
|
702
|
-
|
703
|
-
ot = solver(ot_prob, **kwargs)
|
704
|
+
ot = self.solver(ot_prob, **kwargs)
|
704
705
|
cost = float(ot.reg_ot_cost)
|
705
706
|
|
706
707
|
# Check for NaN or invalid cost
|
pertpy/tools/_milo.py
CHANGED
@@ -364,19 +364,32 @@ class Milo:
|
|
364
364
|
# Set up rpy2 to run edgeR
|
365
365
|
edgeR, limma, stats, base = self._setup_rpy2()
|
366
366
|
|
367
|
+
import rpy2.robjects as ro
|
368
|
+
from rpy2.robjects import numpy2ri, pandas2ri
|
369
|
+
from rpy2.robjects.conversion import localconverter
|
370
|
+
from rpy2.robjects.vectors import FloatVector
|
371
|
+
|
367
372
|
# Define model matrix
|
368
373
|
if not add_intercept or model_contrasts is not None:
|
369
374
|
design = design + " + 0"
|
370
|
-
|
375
|
+
design_df = design_df.astype(dict.fromkeys(design_df.select_dtypes(exclude=["number"]).columns, "category"))
|
376
|
+
with localconverter(ro.default_converter + pandas2ri.converter):
|
377
|
+
design_r = pandas2ri.py2rpy(design_df)
|
378
|
+
formula_r = stats.formula(design)
|
379
|
+
model = stats.model_matrix(object=formula_r, data=design_r)
|
371
380
|
|
372
381
|
# Fit NB-GLM
|
373
|
-
|
382
|
+
counts_filtered = count_mat[np.ix_(keep_nhoods, keep_smp)]
|
383
|
+
lib_size_filtered = lib_size[keep_smp]
|
384
|
+
count_mat_r = numpy2ri.py2rpy(counts_filtered)
|
385
|
+
lib_size_r = FloatVector(lib_size_filtered)
|
386
|
+
dge = edgeR.DGEList(counts=count_mat_r, lib_size=lib_size_r)
|
374
387
|
dge = edgeR.calcNormFactors(dge, method="TMM")
|
375
388
|
dge = edgeR.estimateDisp(dge, model)
|
376
389
|
fit = edgeR.glmQLFit(dge, model, robust=True)
|
377
|
-
|
378
390
|
# Test
|
379
|
-
|
391
|
+
model_np = np.array(model)
|
392
|
+
n_coef = model_np.shape[1]
|
380
393
|
if model_contrasts is not None:
|
381
394
|
r_str = """
|
382
395
|
get_model_cols <- function(design_df, design){
|
@@ -387,32 +400,36 @@ class Milo:
|
|
387
400
|
from rpy2.robjects.packages import STAP
|
388
401
|
|
389
402
|
get_model_cols = STAP(r_str, "get_model_cols")
|
390
|
-
|
391
|
-
|
403
|
+
with localconverter(ro.default_converter + numpy2ri.converter + pandas2ri.converter):
|
404
|
+
model_mat_cols = get_model_cols.get_model_cols(design_df, design)
|
405
|
+
with localconverter(ro.default_converter + pandas2ri.converter + numpy2ri.converter):
|
406
|
+
model_df = pandas2ri.rpy2py(model)
|
407
|
+
model_df = pd.DataFrame(model_df)
|
392
408
|
model_df.columns = model_mat_cols
|
393
409
|
try:
|
394
|
-
|
410
|
+
with localconverter(ro.default_converter + pandas2ri.converter):
|
411
|
+
mod_contrast = limma.makeContrasts(contrasts=model_contrasts, levels=model_df)
|
395
412
|
except ValueError:
|
396
413
|
logger.error("Model contrasts must be in the form 'A-B' or 'A+B'")
|
397
414
|
raise
|
398
|
-
|
399
|
-
|
400
|
-
|
415
|
+
with localconverter(ro.default_converter + pandas2ri.converter + numpy2ri.converter):
|
416
|
+
res = base.as_data_frame(
|
417
|
+
edgeR.topTags(edgeR.glmQLFTest(fit, contrast=mod_contrast), sort_by="none", n=np.inf)
|
418
|
+
)
|
401
419
|
else:
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
res = conversion.rpy2py(res)
|
420
|
+
with localconverter(ro.default_converter + numpy2ri.converter + pandas2ri.converter):
|
421
|
+
res = base.as_data_frame(
|
422
|
+
edgeR.topTags(edgeR.glmQLFTest(fit, coef=n_coef), sort_by="none", n=np.inf)
|
423
|
+
)
|
407
424
|
if not isinstance(res, pd.DataFrame):
|
408
425
|
res = pd.DataFrame(res)
|
409
|
-
|
426
|
+
# The columns of res looks like e.g. table.A, table.B, so remove the prefix
|
427
|
+
res.columns = [col.replace("table.", "") for col in res.columns]
|
410
428
|
# Save outputs
|
411
429
|
res.index = sample_adata.var_names[keep_nhoods] # type: ignore
|
412
430
|
if any(col in sample_adata.var.columns for col in res.columns):
|
413
431
|
sample_adata.var = sample_adata.var.drop(res.columns, axis=1)
|
414
432
|
sample_adata.var = pd.concat([sample_adata.var, res], axis=1)
|
415
|
-
|
416
433
|
# Run Graph spatial FDR correction
|
417
434
|
self._graph_spatial_fdr(sample_adata, neighbors_key=adata.uns["nhood_neighbors_key"])
|
418
435
|
|
@@ -657,11 +674,8 @@ class Milo:
|
|
657
674
|
self,
|
658
675
|
):
|
659
676
|
"""Set up rpy2 to run edgeR."""
|
660
|
-
from rpy2.robjects import numpy2ri, pandas2ri
|
661
677
|
from rpy2.robjects.packages import importr
|
662
678
|
|
663
|
-
numpy2ri.activate()
|
664
|
-
pandas2ri.activate()
|
665
679
|
edgeR = self._try_import_bioc_library("edgeR")
|
666
680
|
limma = self._try_import_bioc_library("limma")
|
667
681
|
stats = importr("stats")
|
@@ -1007,6 +1021,8 @@ class Milo:
|
|
1007
1021
|
subset_nhoods: list[str] = None,
|
1008
1022
|
log_counts: bool = False,
|
1009
1023
|
return_fig: bool = False,
|
1024
|
+
ax=None,
|
1025
|
+
show: bool = True,
|
1010
1026
|
) -> Figure | None:
|
1011
1027
|
"""Plot boxplot of cell numbers vs condition of interest.
|
1012
1028
|
|
@@ -1036,18 +1052,36 @@ class Milo:
|
|
1036
1052
|
pl_df = pd.merge(pl_df, nhood_adata.var)
|
1037
1053
|
pl_df["log_n_cells"] = np.log1p(pl_df["n_cells"])
|
1038
1054
|
if not log_counts:
|
1039
|
-
sns.boxplot(data=pl_df, x=test_var, y="n_cells", color="lightblue")
|
1040
|
-
sns.stripplot(data=pl_df, x=test_var, y="n_cells", color="black", s=3)
|
1041
|
-
|
1055
|
+
sns.boxplot(data=pl_df, x=test_var, y="n_cells", color="lightblue", ax=ax)
|
1056
|
+
sns.stripplot(data=pl_df, x=test_var, y="n_cells", color="black", s=3, ax=ax)
|
1057
|
+
if ax:
|
1058
|
+
ax.set_ylabel("# cells")
|
1059
|
+
else:
|
1060
|
+
plt.ylabel("# cells")
|
1042
1061
|
else:
|
1043
|
-
sns.boxplot(data=pl_df, x=test_var, y="log_n_cells", color="lightblue")
|
1044
|
-
sns.stripplot(data=pl_df, x=test_var, y="log_n_cells", color="black", s=3)
|
1045
|
-
|
1062
|
+
sns.boxplot(data=pl_df, x=test_var, y="log_n_cells", color="lightblue", ax=ax)
|
1063
|
+
sns.stripplot(data=pl_df, x=test_var, y="log_n_cells", color="black", s=3, ax=ax)
|
1064
|
+
if ax:
|
1065
|
+
ax.set_ylabel("log(# cells + 1)")
|
1066
|
+
else:
|
1067
|
+
plt.ylabel("log(# cells + 1)")
|
1046
1068
|
|
1047
|
-
|
1048
|
-
|
1069
|
+
if ax:
|
1070
|
+
ax.tick_params(axis="x", rotation=90)
|
1071
|
+
ax.set_xlabel(test_var)
|
1072
|
+
else:
|
1073
|
+
plt.xticks(rotation=90)
|
1074
|
+
plt.xlabel(test_var)
|
1049
1075
|
|
1050
1076
|
if return_fig:
|
1051
1077
|
return plt.gcf()
|
1052
|
-
|
1078
|
+
|
1079
|
+
if ax is None:
|
1080
|
+
plt.show()
|
1081
|
+
|
1082
|
+
if return_fig:
|
1083
|
+
return plt.gcf()
|
1084
|
+
if show:
|
1085
|
+
plt.show()
|
1086
|
+
|
1053
1087
|
return None
|
pertpy/tools/_mixscape.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import copy
|
4
|
+
import warnings
|
4
5
|
from collections import OrderedDict
|
5
6
|
from typing import TYPE_CHECKING, Literal
|
6
7
|
|
@@ -10,11 +11,12 @@ import pandas as pd
|
|
10
11
|
import scanpy as sc
|
11
12
|
import seaborn as sns
|
12
13
|
from fast_array_utils.stats import mean, mean_var
|
14
|
+
from pandas.errors import PerformanceWarning
|
13
15
|
from scanpy import get
|
14
16
|
from scanpy._utils import _check_use_raw, sanitize_anndata
|
15
17
|
from scanpy.plotting import _utils
|
16
18
|
from scanpy.tools._utils import _choose_representation
|
17
|
-
from scipy.sparse import csr_matrix, spmatrix
|
19
|
+
from scipy.sparse import csr_matrix, issparse, spmatrix
|
18
20
|
from sklearn.mixture import GaussianMixture
|
19
21
|
|
20
22
|
from pertpy._doc import _doc_params, doc_common_plot_args
|
@@ -103,6 +105,9 @@ class Mixscape:
|
|
103
105
|
|
104
106
|
adata.layers["X_pert"] = adata.X.copy()
|
105
107
|
|
108
|
+
# Work with LIL for efficient indexing but don't store it in AnnData as LIL is not supported anymore
|
109
|
+
X_pert_lil = adata.layers["X_pert"].tolil() if issparse(adata.layers["X_pert"]) else adata.layers["X_pert"]
|
110
|
+
|
106
111
|
control_mask = adata.obs[pert_key] == control
|
107
112
|
|
108
113
|
if ref_selection_mode == "split_by":
|
@@ -110,9 +115,8 @@ class Mixscape:
|
|
110
115
|
split_mask = adata.obs[split_by] == split
|
111
116
|
control_mask_group = control_mask & split_mask
|
112
117
|
control_mean_expr = mean(adata.X[control_mask_group], axis=0)
|
113
|
-
|
114
|
-
np.repeat(control_mean_expr.reshape(1, -1), split_mask.sum(), axis=0)
|
115
|
-
- adata.layers["X_pert"][split_mask]
|
118
|
+
X_pert_lil[split_mask] = (
|
119
|
+
np.repeat(control_mean_expr.reshape(1, -1), split_mask.sum(), axis=0) - X_pert_lil[split_mask]
|
116
120
|
)
|
117
121
|
else:
|
118
122
|
if split_by is None:
|
@@ -129,49 +133,43 @@ class Mixscape:
|
|
129
133
|
|
130
134
|
for split_mask in split_masks:
|
131
135
|
control_mask_split = control_mask & split_mask
|
132
|
-
|
133
136
|
R_split = representation[split_mask]
|
134
137
|
R_control = representation[np.asarray(control_mask_split)]
|
135
|
-
|
136
138
|
eps = kwargs.pop("epsilon", 0.1)
|
137
139
|
nn_index = NNDescent(R_control, **kwargs)
|
138
140
|
indices, _ = nn_index.query(R_split, k=n_neighbors, epsilon=eps)
|
139
|
-
|
140
141
|
X_control = np.expm1(adata.X[np.asarray(control_mask_split)])
|
141
|
-
|
142
142
|
n_split = split_mask.sum()
|
143
143
|
n_control = X_control.shape[0]
|
144
144
|
|
145
145
|
if batch_size is None:
|
146
146
|
col_indices = np.ravel(indices)
|
147
147
|
row_indices = np.repeat(np.arange(n_split), n_neighbors)
|
148
|
-
|
149
148
|
neigh_matrix = csr_matrix(
|
150
149
|
(np.ones_like(col_indices, dtype=np.float64), (row_indices, col_indices)),
|
151
150
|
shape=(n_split, n_control),
|
152
151
|
)
|
153
152
|
neigh_matrix /= n_neighbors
|
154
|
-
|
155
|
-
sc.pp.log1p(neigh_matrix @ X_control) -
|
153
|
+
X_pert_lil[np.asarray(split_mask)] = (
|
154
|
+
sc.pp.log1p(neigh_matrix @ X_control) - X_pert_lil[np.asarray(split_mask)]
|
156
155
|
)
|
157
156
|
else:
|
158
157
|
split_indices = np.where(split_mask)[0]
|
159
158
|
for i in range(0, n_split, batch_size):
|
160
159
|
size = min(i + batch_size, n_split)
|
161
160
|
select = slice(i, size)
|
162
|
-
|
163
161
|
batch = np.ravel(indices[select])
|
164
162
|
split_batch = split_indices[select]
|
165
|
-
|
166
163
|
size = size - i
|
167
|
-
|
168
164
|
means_batch = X_control[batch]
|
169
165
|
batch_reshaped = means_batch.reshape(size, n_neighbors, -1)
|
170
166
|
means_batch, _ = mean_var(batch_reshaped, axis=1)
|
167
|
+
X_pert_lil[split_batch] = np.log1p(means_batch) - X_pert_lil[split_batch]
|
171
168
|
|
172
|
-
|
173
|
-
|
174
|
-
|
169
|
+
if issparse(X_pert_lil):
|
170
|
+
adata.layers["X_pert"] = X_pert_lil.tocsr()
|
171
|
+
else:
|
172
|
+
adata.layers["X_pert"] = X_pert_lil
|
175
173
|
|
176
174
|
if copy:
|
177
175
|
return adata
|
@@ -531,26 +529,29 @@ class Mixscape:
|
|
531
529
|
gene_targets = list(set(adata[split_mask].obs[labels]).difference([control]))
|
532
530
|
adata_split = adata[split_mask].copy()
|
533
531
|
# find top DE genes between cells with targeting and non-targeting gRNAs
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
logfc_threshold_mask = (
|
546
|
-
np.abs(adata_split.uns["rank_genes_groups"]["logfoldchanges"][gene]) >= logfc_threshold
|
532
|
+
with warnings.catch_warnings():
|
533
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
534
|
+
warnings.simplefilter("ignore", PerformanceWarning)
|
535
|
+
sc.tl.rank_genes_groups(
|
536
|
+
adata_split,
|
537
|
+
layer=layer,
|
538
|
+
groupby=labels,
|
539
|
+
groups=gene_targets,
|
540
|
+
reference=control,
|
541
|
+
method=test_method,
|
542
|
+
use_raw=False,
|
547
543
|
)
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
544
|
+
# get DE genes for each target gene
|
545
|
+
for gene in gene_targets:
|
546
|
+
logfc_threshold_mask = (
|
547
|
+
np.abs(adata_split.uns["rank_genes_groups"]["logfoldchanges"][gene]) >= logfc_threshold
|
548
|
+
)
|
549
|
+
de_genes = adata_split.uns["rank_genes_groups"]["names"][gene][logfc_threshold_mask]
|
550
|
+
pvals_adj = adata_split.uns["rank_genes_groups"]["pvals_adj"][gene][logfc_threshold_mask]
|
551
|
+
de_genes = de_genes[pvals_adj < pval_cutoff]
|
552
|
+
if len(de_genes) < min_de_genes:
|
553
|
+
de_genes = np.array([])
|
554
|
+
perturbation_markers[(category, gene)] = de_genes
|
554
555
|
|
555
556
|
return perturbation_markers
|
556
557
|
|
@@ -711,7 +712,10 @@ class Mixscape:
|
|
711
712
|
if "mixscape_class" not in adata.obs:
|
712
713
|
raise ValueError("Please run `pt.tl.mixscape` first.")
|
713
714
|
adata_subset = adata[(adata.obs[labels] == target_gene) | (adata.obs[labels] == control)].copy()
|
714
|
-
|
715
|
+
with warnings.catch_warnings():
|
716
|
+
warnings.simplefilter("ignore", RuntimeWarning)
|
717
|
+
warnings.simplefilter("ignore", PerformanceWarning)
|
718
|
+
sc.tl.rank_genes_groups(adata_subset, layer=layer, groupby=labels, method=method)
|
715
719
|
sc.pp.scale(adata_subset, max_value=vmax)
|
716
720
|
sc.pp.subsample(adata_subset, n_obs=subsample_number)
|
717
721
|
|
@@ -998,8 +1002,7 @@ class Mixscape:
|
|
998
1002
|
ys = keys
|
999
1003
|
|
1000
1004
|
if multi_panel and groupby is None and len(ys) == 1:
|
1001
|
-
# This is a quick and dirty way for adapting scales across several
|
1002
|
-
# keys if groupby is None.
|
1005
|
+
# This is a quick and dirty way for adapting scales across several keys if groupby is None.
|
1003
1006
|
y = ys[0]
|
1004
1007
|
|
1005
1008
|
g = sns.catplot(
|
@@ -226,7 +226,7 @@ class MLPClassifierSpace(PerturbationSpace):
|
|
226
226
|
# Fix class unbalance (likely to happen in perturbation datasets)
|
227
227
|
# Usually control cells are overrepresented such that predicting control all time would give good results
|
228
228
|
# Cells with rare perturbations are sampled more
|
229
|
-
train_weights = 1 / (1 + torch.sum(torch.tensor(train_dataset.labels), dim=1))
|
229
|
+
train_weights = 1 / (1 + torch.sum(torch.tensor(train_dataset.labels.to_list()), dim=1))
|
230
230
|
train_sampler = WeightedRandomSampler(train_weights, len(train_weights))
|
231
231
|
|
232
232
|
self.train_dataloader = DataLoader(train_dataset, batch_size=batch_size, sampler=train_sampler, num_workers=4)
|
pertpy/tools/_scgen/_scgen.py
CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
4
4
|
|
5
|
+
import anndata as ad
|
5
6
|
import jax.numpy as jnp
|
6
7
|
import matplotlib.pyplot as plt
|
7
8
|
import numpy as np
|
@@ -248,7 +249,7 @@ class Scgen(JaxTrainingMixin, BaseModelClass):
|
|
248
249
|
temp_cell[batch_ind[study]].X = batch_list[study].X
|
249
250
|
shared_ct.append(temp_cell)
|
250
251
|
|
251
|
-
all_shared_ann =
|
252
|
+
all_shared_ann = ad.concat(shared_ct, label="concat_batch", index_unique=None)
|
252
253
|
if "concat_batch" in all_shared_ann.obs.columns:
|
253
254
|
del all_shared_ann.obs["concat_batch"]
|
254
255
|
if len(not_shared_ct) < 1:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pertpy
|
3
|
-
Version: 0.11.
|
3
|
+
Version: 0.11.5
|
4
4
|
Summary: Perturbation Analysis in the scverse ecosystem.
|
5
5
|
Project-URL: Documentation, https://pertpy.readthedocs.io
|
6
6
|
Project-URL: Source, https://github.com/scverse/pertpy
|
@@ -131,6 +131,12 @@ You can install _pertpy_ in less than a minute via [pip] from [PyPI]:
|
|
131
131
|
pip install pertpy
|
132
132
|
```
|
133
133
|
|
134
|
+
or [conda-forge]:
|
135
|
+
|
136
|
+
```console
|
137
|
+
conda install -c conda-forge pertpy
|
138
|
+
```
|
139
|
+
|
134
140
|
### Differential gene expression
|
135
141
|
|
136
142
|
If you want to use the differential gene expression interface, please install pertpy by running:
|
@@ -179,6 +185,7 @@ pip install rpy2
|
|
179
185
|
[pip]: https://pip.pypa.io/
|
180
186
|
[pypi]: https://pypi.org/
|
181
187
|
[api]: https://pertpy.readthedocs.io/en/latest/api.html
|
188
|
+
[conda-forge]: https://anaconda.org/conda-forge/pertpy
|
182
189
|
[//]: # "numfocus-fiscal-sponsor-attribution"
|
183
190
|
|
184
191
|
pertpy is part of the scverse® project ([website](https://scverse.org), [governance](https://scverse.org/about/roles)) and is fiscally sponsored by [NumFOCUS](https://numfocus.org/).
|
@@ -1,4 +1,4 @@
|
|
1
|
-
pertpy/__init__.py,sha256=
|
1
|
+
pertpy/__init__.py,sha256=KIxMlqyHlppcGM5Uc2HpTwCEtGFavXRPW50dM5dFB7U,716
|
2
2
|
pertpy/_doc.py,sha256=j5TMNC-DA9yIMqIIUNpjpcVgWfRqyBBfvbRjnCM_OLs,427
|
3
3
|
pertpy/_types.py,sha256=IcHCojCUqx8CapibNkcYf2TUqjBFP2ujeELvn_IBSBQ,154
|
4
4
|
pertpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -21,12 +21,12 @@ pertpy/tools/_augur.py,sha256=tc1YKyc0BwzrEGgctsfyy7DsTNKxyvy7ZvWraTWCc1A,55262
|
|
21
21
|
pertpy/tools/_cinemaot.py,sha256=54-rS0AEj31dMe7iU4kEmLoAunq3jNuhsBE3IEp9hrI,38071
|
22
22
|
pertpy/tools/_dialogue.py,sha256=mygIZm5i_bnEE37TTQtr1efl_KJq-ejzeL3V1Bmr7Pg,52354
|
23
23
|
pertpy/tools/_enrichment.py,sha256=55mwotLH9DXQOhl85MCkxXu-MX0RysLyrPheJysAnF0,21369
|
24
|
-
pertpy/tools/_milo.py,sha256=
|
25
|
-
pertpy/tools/_mixscape.py,sha256=
|
24
|
+
pertpy/tools/_milo.py,sha256=zIYG0aP8B39_eiNgpZONhTKmDvcRwCzOLo5FMOTMUms,45530
|
25
|
+
pertpy/tools/_mixscape.py,sha256=HfrpBeRlxHXaOpZkF2FmX7dg35kUB1rL0_-n2aSi2_0,57905
|
26
26
|
pertpy/tools/decoupler_LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
27
27
|
pertpy/tools/transferlearning_MMD_LICENSE,sha256=MUvDA-o_j9htRpI8fStVdCRuyLdPkQUuIH0a_EIc57w,1069
|
28
28
|
pertpy/tools/_coda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
|
-
pertpy/tools/_coda/_base_coda.py,sha256=
|
29
|
+
pertpy/tools/_coda/_base_coda.py,sha256=NjKIQBtTIUENnRmeIC2O8cMdU_9DKaJ5_AHPvFnc8XQ,111744
|
30
30
|
pertpy/tools/_coda/_sccoda.py,sha256=0Ret6O56kAfCNOdBvtxqiyuj2rUPp18SV1GVK1AvYGU,22607
|
31
31
|
pertpy/tools/_coda/_tasccoda.py,sha256=BTaOAmL458zQ_og3x4ENlDnJHD6_F4YkdCoXWsF4i1U,30465
|
32
32
|
pertpy/tools/_differential_gene_expression/__init__.py,sha256=SEydWg0iT3Y1pApjnCAOuHxFeI6xVUfgyBHv2s3LADU,487
|
@@ -39,20 +39,20 @@ pertpy/tools/_differential_gene_expression/_simple_tests.py,sha256=SfU8s_P2JzEA1
|
|
39
39
|
pertpy/tools/_differential_gene_expression/_statsmodels.py,sha256=90h9EPuoCtNxAbJ1Xq4j_E4yYJJpk64zTP7GyTdmrxY,2220
|
40
40
|
pertpy/tools/_distances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
41
41
|
pertpy/tools/_distances/_distance_tests.py,sha256=6_nqfHUfKxkI2Yhkzspq3ujMpq56zV_Ddn7bgPzgjyo,13513
|
42
|
-
pertpy/tools/_distances/_distances.py,sha256=
|
42
|
+
pertpy/tools/_distances/_distances.py,sha256=_XbVU8dlYt_Jl2thYPUWg7HT6OXVe-Ki6qthF566sqQ,50503
|
43
43
|
pertpy/tools/_perturbation_space/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
44
|
pertpy/tools/_perturbation_space/_clustering.py,sha256=pNx_SpPkZfCbgF7vzHWqAaiiHdbxPaA-L-hTWTbzFhI,3528
|
45
45
|
pertpy/tools/_perturbation_space/_comparison.py,sha256=-NzCPRT-IlhJ9hOz7NQLSk0riIzr2C0yZvX6zm3kon4,4291
|
46
|
-
pertpy/tools/_perturbation_space/_discriminator_classifiers.py,sha256=
|
46
|
+
pertpy/tools/_perturbation_space/_discriminator_classifiers.py,sha256=a53-YmUwDHQBCT7ZWe_RH7PZsGXvoSHmJaQyL0CBJng,23383
|
47
47
|
pertpy/tools/_perturbation_space/_metrics.py,sha256=y8-baP8WRdB1iDgvP3uuQxSCDxA2lcxvEHHM2C_vWHY,3248
|
48
48
|
pertpy/tools/_perturbation_space/_perturbation_space.py,sha256=8RxVUkVEPZj5YZ-C-NP5zO4aYYVD04PzlsYuaIG-wjY,19447
|
49
49
|
pertpy/tools/_perturbation_space/_simple.py,sha256=AJlHRaEP-vViBeMDvvMtUnXMuIKqZVc7wggnjsHMfMw,12721
|
50
50
|
pertpy/tools/_scgen/__init__.py,sha256=uERFlFyF88TH0uLiwmsUGEfHfLVCiZMFuk8gO5f7164,45
|
51
51
|
pertpy/tools/_scgen/_base_components.py,sha256=Qq8myRUm43q9XBrZ9gBggfa2cSV2wbz_KYoLgH7iF1A,3009
|
52
|
-
pertpy/tools/_scgen/_scgen.py,sha256=
|
52
|
+
pertpy/tools/_scgen/_scgen.py,sha256=AQNGsDe-9HEqli3oq7UBDg68ofLCoXm-R_jnLFQ-rlc,30856
|
53
53
|
pertpy/tools/_scgen/_scgenvae.py,sha256=bPk4v7EdJc7ROdLuDitHiX_Pvwa7Flw2qHRUwBvjLJY,3889
|
54
54
|
pertpy/tools/_scgen/_utils.py,sha256=qz5QUn_Bvk2NGyYVzp3jgjWTFOMt1YyHwUo6HWtoThY,2871
|
55
|
-
pertpy-0.11.
|
56
|
-
pertpy-0.11.
|
57
|
-
pertpy-0.11.
|
58
|
-
pertpy-0.11.
|
55
|
+
pertpy-0.11.5.dist-info/METADATA,sha256=YEYgYTHkjmyWyboRL3RhBaSxOw86O5vr0wpXdvaLTGk,8827
|
56
|
+
pertpy-0.11.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
57
|
+
pertpy-0.11.5.dist-info/licenses/LICENSE,sha256=XuiT2hxeRInhquEIBKMZ5M21n5syhDQ4XbABoposIAg,1100
|
58
|
+
pertpy-0.11.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|