discotoolkit 1.3.1__tar.gz → 1.3.2__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.
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/PKG-INFO +4 -5
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/README.md +2 -2
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/CELLiD.py +36 -28
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/__init__.py +1 -1
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit.egg-info/PKG-INFO +4 -5
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit.egg-info/SOURCES.txt +1 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit.egg-info/requires.txt +1 -2
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/requirements.txt +1 -2
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/setup.py +1 -1
- discotoolkit-1.3.2/tests/test_cellid_correlation.py +91 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/MANIFEST.in +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/CellMapper.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/DiscoClass.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/DownloadDiscoData.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/GeneSearch.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/GetMetadata.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/GlobalVariable.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit/Utilities.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit.egg-info/dependency_links.txt +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/discotoolkit.egg-info/top_level.txt +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/pyproject.toml +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/setup.cfg +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_docs.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_gene_search.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_metadata_helpers.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_reference_loading.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_server_contract.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_settings.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.2}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: discotoolkit
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: DISCOtoolkit is an python package that allows users to access data and use the tools provided by the DISCO database.
|
|
5
5
|
Home-page: https://disco.bii.a-star.edu.sg/
|
|
6
6
|
Author: Li Mengwei, Rom Uddamvathanak
|
|
@@ -11,12 +11,11 @@ Project-URL: Issues, https://github.com/JinmiaoChenLab/DISCOtoolkit_py/issues
|
|
|
11
11
|
Project-URL: DISCO, https://disco.bii.a-star.edu.sg/v1/
|
|
12
12
|
Requires-Python: >=3.9
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
-
Requires-Dist: pandas
|
|
14
|
+
Requires-Dist: pandas>=1.4.2
|
|
15
15
|
Requires-Dist: numpy>=1.21.6
|
|
16
16
|
Requires-Dist: scanpy>=1.9.3
|
|
17
17
|
Requires-Dist: scipy>=1.10.1
|
|
18
18
|
Requires-Dist: joblib>=1.1.0
|
|
19
|
-
Requires-Dist: pandarallel>=1.6.5
|
|
20
19
|
Requires-Dist: requests>=2.28.1
|
|
21
20
|
Requires-Dist: colorcet>=3.0.1
|
|
22
21
|
Requires-Dist: leidenalg
|
|
@@ -43,7 +42,7 @@ Dynamic: summary
|
|
|
43
42
|
-->
|
|
44
43
|
[](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [](https://pepy.tech/project/discotoolkit) [](https://pypi.org/project/discotoolkit)
|
|
45
44
|
|
|
46
|
-
# DISCOtoolkit 1.3.
|
|
45
|
+
# DISCOtoolkit 1.3.2
|
|
47
46
|
|
|
48
47
|
DISCOtoolkit is a Python package for accessing the data and tools of the [DISCO database](https://disco.bii.a-star.edu.sg/) (DISCO v1). Read the documentation, with tutorials and the API reference, at [disco.bii.a-star.edu.sg/v1/docs/toolkit/guide](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/).
|
|
49
48
|
|
|
@@ -84,7 +83,7 @@ pip install -e .
|
|
|
84
83
|
|
|
85
84
|
`pip install discotoolkit` and a local install give the same code when the versions match. The difference is the source: PyPI delivers a released, packaged copy, while a local install uses the files in your folder.
|
|
86
85
|
|
|
87
|
-
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib,
|
|
86
|
+
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
|
|
88
87
|
|
|
89
88
|
We recommend a virtual environment, for example with miniconda:
|
|
90
89
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
-->
|
|
9
9
|
[](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [](https://pepy.tech/project/discotoolkit) [](https://pypi.org/project/discotoolkit)
|
|
10
10
|
|
|
11
|
-
# DISCOtoolkit 1.3.
|
|
11
|
+
# DISCOtoolkit 1.3.2
|
|
12
12
|
|
|
13
13
|
DISCOtoolkit is a Python package for accessing the data and tools of the [DISCO database](https://disco.bii.a-star.edu.sg/) (DISCO v1). Read the documentation, with tutorials and the API reference, at [disco.bii.a-star.edu.sg/v1/docs/toolkit/guide](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/).
|
|
14
14
|
|
|
@@ -49,7 +49,7 @@ pip install -e .
|
|
|
49
49
|
|
|
50
50
|
`pip install discotoolkit` and a local install give the same code when the versions match. The difference is the source: PyPI delivers a released, packaged copy, while a local install uses the files in your folder.
|
|
51
51
|
|
|
52
|
-
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib,
|
|
52
|
+
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
|
|
53
53
|
|
|
54
54
|
We recommend a virtual environment, for example with miniconda:
|
|
55
55
|
|
|
@@ -13,10 +13,43 @@ from scipy import stats
|
|
|
13
13
|
# from fast_fisher import fast_fisher_exact, odds_ratio
|
|
14
14
|
from scipy.stats.contingency import odds_ratio
|
|
15
15
|
from joblib import Parallel, delayed # multiprocessing library
|
|
16
|
-
from pandarallel import pandarallel # multiprocessing library
|
|
17
16
|
|
|
18
17
|
pd.options.mode.chained_assignment = None
|
|
19
18
|
|
|
19
|
+
|
|
20
|
+
def _spearman_matrix(ref_data: pd.DataFrame, rna) -> np.ndarray:
|
|
21
|
+
"""Spearman correlation of every reference column with every user column (reference x user).
|
|
22
|
+
|
|
23
|
+
Spearman is Pearson on ranks, so with no missing values the whole table is one matrix product and needs no
|
|
24
|
+
process pool. Columns with a missing value fall back to pandas' own pairwise-complete Series.corr, which
|
|
25
|
+
gives the same numbers as before for them. A constant column has no defined correlation and gives NaN.
|
|
26
|
+
"""
|
|
27
|
+
ref = pd.DataFrame(ref_data)
|
|
28
|
+
user = pd.DataFrame(rna)
|
|
29
|
+
ref_values = ref.to_numpy(dtype=float)
|
|
30
|
+
user_values = user.to_numpy(dtype=float)
|
|
31
|
+
result = np.full((ref_values.shape[1], user_values.shape[1]), np.nan)
|
|
32
|
+
|
|
33
|
+
ref_ok = ~np.isnan(ref_values).any(axis=0)
|
|
34
|
+
user_ok = ~np.isnan(user_values).any(axis=0)
|
|
35
|
+
|
|
36
|
+
def standardised_ranks(frame: pd.DataFrame, columns: np.ndarray) -> np.ndarray:
|
|
37
|
+
ranks = frame.iloc[:, np.flatnonzero(columns)].rank(axis=0, method="average").to_numpy(dtype=float)
|
|
38
|
+
ranks = ranks - ranks.mean(axis=0)
|
|
39
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
40
|
+
return ranks / np.sqrt((ranks**2).sum(axis=0))
|
|
41
|
+
|
|
42
|
+
if ref_ok.any() and user_ok.any():
|
|
43
|
+
block = standardised_ranks(ref, ref_ok).T @ standardised_ranks(user, user_ok)
|
|
44
|
+
result[np.ix_(np.flatnonzero(ref_ok), np.flatnonzero(user_ok))] = np.clip(block, -1.0, 1.0)
|
|
45
|
+
|
|
46
|
+
# Anything touching a missing value is done pair by pair, as pandas always did.
|
|
47
|
+
for j in range(user_values.shape[1]):
|
|
48
|
+
for i in range(ref_values.shape[1]):
|
|
49
|
+
if not (ref_ok[i] and user_ok[j]):
|
|
50
|
+
result[i, j] = pd.Series(ref_values[:, i]).corr(pd.Series(user_values[:, j]), method="spearman")
|
|
51
|
+
return result
|
|
52
|
+
|
|
20
53
|
# import variable and class from other script
|
|
21
54
|
from .GlobalVariable import logging, api_url, timeout
|
|
22
55
|
from .DiscoClass import FilterData, Filter
|
|
@@ -183,9 +216,6 @@ def CELLiD_cluster(
|
|
|
183
216
|
Pandas DataFrame: return the Pandas DataFrame along with the correlation score.
|
|
184
217
|
"""
|
|
185
218
|
|
|
186
|
-
# initialize the pandarallel for parallel processing
|
|
187
|
-
pandarallel.initialize(nb_workers=ncores)
|
|
188
|
-
|
|
189
219
|
# check for the input data
|
|
190
220
|
if not (isinstance(rna, pd.DataFrame) or isinstance(rna, np.ndarray)):
|
|
191
221
|
logging.error("the rna must be a pandas DataFrame or Numpy Array")
|
|
@@ -247,30 +277,8 @@ def CELLiD_cluster(
|
|
|
247
277
|
rna = rna.loc[list(genes)]
|
|
248
278
|
ref_data = ref_data.loc[list(genes)]
|
|
249
279
|
|
|
250
|
-
#
|
|
251
|
-
|
|
252
|
-
input = list(input)
|
|
253
|
-
res = ref_data.parallel_apply(basic_correlation, input=input, axis=0)
|
|
254
|
-
return res
|
|
255
|
-
|
|
256
|
-
# apply the correlation to all the columns in user data
|
|
257
|
-
def basic_correlation(ref, input):
|
|
258
|
-
# predicted = stats.spearmanr(
|
|
259
|
-
# np.asarray(ref), np.asarray(input), alternative = "two-sided", nan_policy='omit'
|
|
260
|
-
# )[0]
|
|
261
|
-
predicted = pd.Series(list(ref)).corr(pd.Series(list(input)), method="spearman")
|
|
262
|
-
|
|
263
|
-
return predicted
|
|
264
|
-
|
|
265
|
-
# get the predicted correlation as in pandas DataFrame
|
|
266
|
-
# predicted_cell = pd.DataFrame(
|
|
267
|
-
# generate_correlation_map(ref_data.to_numpy().T, rna.to_numpy().T)
|
|
268
|
-
# )
|
|
269
|
-
predicted_cell = rna.apply(
|
|
270
|
-
each_ref_correlation, result_type="expand", axis=0, ref_data=ref_data
|
|
271
|
-
)
|
|
272
|
-
predicted_cell = pd.DataFrame(predicted_cell)
|
|
273
|
-
|
|
280
|
+
# correlation of every user column with every reference cell type (rows: cell types, columns: user clusters)
|
|
281
|
+
predicted_cell = pd.DataFrame(_spearman_matrix(ref_data, rna), columns=rna.columns)
|
|
274
282
|
# set the index to be the celltype based on the reference_data
|
|
275
283
|
predicted_cell.index = ref_data.columns
|
|
276
284
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: discotoolkit
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: DISCOtoolkit is an python package that allows users to access data and use the tools provided by the DISCO database.
|
|
5
5
|
Home-page: https://disco.bii.a-star.edu.sg/
|
|
6
6
|
Author: Li Mengwei, Rom Uddamvathanak
|
|
@@ -11,12 +11,11 @@ Project-URL: Issues, https://github.com/JinmiaoChenLab/DISCOtoolkit_py/issues
|
|
|
11
11
|
Project-URL: DISCO, https://disco.bii.a-star.edu.sg/v1/
|
|
12
12
|
Requires-Python: >=3.9
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
-
Requires-Dist: pandas
|
|
14
|
+
Requires-Dist: pandas>=1.4.2
|
|
15
15
|
Requires-Dist: numpy>=1.21.6
|
|
16
16
|
Requires-Dist: scanpy>=1.9.3
|
|
17
17
|
Requires-Dist: scipy>=1.10.1
|
|
18
18
|
Requires-Dist: joblib>=1.1.0
|
|
19
|
-
Requires-Dist: pandarallel>=1.6.5
|
|
20
19
|
Requires-Dist: requests>=2.28.1
|
|
21
20
|
Requires-Dist: colorcet>=3.0.1
|
|
22
21
|
Requires-Dist: leidenalg
|
|
@@ -43,7 +42,7 @@ Dynamic: summary
|
|
|
43
42
|
-->
|
|
44
43
|
[](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [](https://pepy.tech/project/discotoolkit) [](https://pypi.org/project/discotoolkit)
|
|
45
44
|
|
|
46
|
-
# DISCOtoolkit 1.3.
|
|
45
|
+
# DISCOtoolkit 1.3.2
|
|
47
46
|
|
|
48
47
|
DISCOtoolkit is a Python package for accessing the data and tools of the [DISCO database](https://disco.bii.a-star.edu.sg/) (DISCO v1). Read the documentation, with tutorials and the API reference, at [disco.bii.a-star.edu.sg/v1/docs/toolkit/guide](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/).
|
|
49
48
|
|
|
@@ -84,7 +83,7 @@ pip install -e .
|
|
|
84
83
|
|
|
85
84
|
`pip install discotoolkit` and a local install give the same code when the versions match. The difference is the source: PyPI delivers a released, packaged copy, while a local install uses the files in your folder.
|
|
86
85
|
|
|
87
|
-
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib,
|
|
86
|
+
Dependencies (installed automatically): numpy, pandas, scanpy, scipy, joblib, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
|
|
88
87
|
|
|
89
88
|
We recommend a virtual environment, for example with miniconda:
|
|
90
89
|
|
|
@@ -17,6 +17,7 @@ discotoolkit.egg-info/SOURCES.txt
|
|
|
17
17
|
discotoolkit.egg-info/dependency_links.txt
|
|
18
18
|
discotoolkit.egg-info/requires.txt
|
|
19
19
|
discotoolkit.egg-info/top_level.txt
|
|
20
|
+
tests/test_cellid_correlation.py
|
|
20
21
|
tests/test_docs.py
|
|
21
22
|
tests/test_gene_search.py
|
|
22
23
|
tests/test_metadata_helpers.py
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CELLiD's correlation step: the matrix calculation that replaced pandarallel must give the numbers pandas'
|
|
3
|
+
own pairwise Spearman gives (ties, missing values, constant columns included), and CELLiD_cluster must
|
|
4
|
+
annotate a small made-up reference correctly. No network.
|
|
5
|
+
|
|
6
|
+
python tests/test_cellid_correlation.py
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pandas as pd
|
|
13
|
+
|
|
14
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
15
|
+
from discotoolkit.CELLiD import CELLiD_cluster, _spearman_matrix # noqa: E402
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def pandas_pairwise(ref: pd.DataFrame, user: pd.DataFrame) -> np.ndarray:
|
|
19
|
+
"""What the code did before: one Series.corr(method="spearman") per pair."""
|
|
20
|
+
return np.array([[pd.Series(ref.iloc[:, i].to_numpy()).corr(pd.Series(user.iloc[:, j].to_numpy()), method="spearman")
|
|
21
|
+
for j in range(user.shape[1])] for i in range(ref.shape[1])])
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def same(a, b):
|
|
25
|
+
assert a.shape == b.shape, (a.shape, b.shape)
|
|
26
|
+
assert np.array_equal(np.isnan(a), np.isnan(b)), "NaN positions differ"
|
|
27
|
+
assert np.allclose(a[~np.isnan(a)], b[~np.isnan(b)], atol=1e-12), np.nanmax(np.abs(a - b))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_matches_pandas_on_continuous_data():
|
|
31
|
+
rng = np.random.default_rng(1)
|
|
32
|
+
ref = pd.DataFrame(rng.normal(size=(300, 12)))
|
|
33
|
+
user = pd.DataFrame(rng.normal(size=(300, 5)))
|
|
34
|
+
same(_spearman_matrix(ref, user), pandas_pairwise(ref, user))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_matches_pandas_with_many_ties_like_expression_data():
|
|
38
|
+
rng = np.random.default_rng(2)
|
|
39
|
+
ref = pd.DataFrame(rng.poisson(0.4, size=(400, 10)).astype(float))
|
|
40
|
+
user = pd.DataFrame(rng.poisson(0.4, size=(400, 4)).astype(float))
|
|
41
|
+
same(_spearman_matrix(ref, user), pandas_pairwise(ref, user))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_missing_values_use_pairwise_complete_observations():
|
|
45
|
+
rng = np.random.default_rng(3)
|
|
46
|
+
ref = pd.DataFrame(rng.normal(size=(200, 6)))
|
|
47
|
+
user = pd.DataFrame(rng.normal(size=(200, 3)))
|
|
48
|
+
ref.iloc[5, 2] = np.nan
|
|
49
|
+
user.iloc[17, 1] = np.nan
|
|
50
|
+
same(_spearman_matrix(ref, user), pandas_pairwise(ref, user))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_a_constant_column_has_no_correlation():
|
|
54
|
+
rng = np.random.default_rng(4)
|
|
55
|
+
ref = pd.DataFrame(rng.normal(size=(50, 3)))
|
|
56
|
+
ref[1] = 7.0
|
|
57
|
+
user = pd.DataFrame(rng.normal(size=(50, 2)))
|
|
58
|
+
result = _spearman_matrix(ref, user)
|
|
59
|
+
assert np.isnan(result[1]).all() and not np.isnan(result[[0, 2]]).any()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_cellid_cluster_annotates_a_small_reference():
|
|
63
|
+
rng = np.random.default_rng(5)
|
|
64
|
+
genes = ["G%d" % i for i in range(300)]
|
|
65
|
+
types = ["B cell--blood", "T cell--blood", "Macrophage--lung", "Fibroblast--lung"]
|
|
66
|
+
ref = pd.DataFrame(rng.poisson(1.0, size=(300, 4)).astype(float), index=genes, columns=types)
|
|
67
|
+
# every cluster is a noisy copy of one reference cell type
|
|
68
|
+
picks = [2, 0, 3]
|
|
69
|
+
user = pd.DataFrame({str(c): ref.iloc[:, t] + rng.normal(0, 0.2, size=300) for c, t in enumerate(picks)}, index=genes)
|
|
70
|
+
deg = pd.DataFrame([(t, g) for t in types for g in genes[:150]], columns=["group", "gene"])
|
|
71
|
+
out = CELLiD_cluster(user, ref_data=ref, ref_deg=deg, n_predict=1, ncores=1)
|
|
72
|
+
assert list(out["predicted_cell_type_1"]) == ["Macrophage", "B cell", "Fibroblast"], out
|
|
73
|
+
assert list(out["source_atlas_1"]) == ["lung", "blood", "lung"], out
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _run_all():
|
|
77
|
+
tests = [(n, f) for n, f in sorted(globals().items()) if n.startswith("test_") and callable(f)]
|
|
78
|
+
failed = 0
|
|
79
|
+
for name, fn in tests:
|
|
80
|
+
try:
|
|
81
|
+
fn()
|
|
82
|
+
print(" PASS %s" % name)
|
|
83
|
+
except Exception as error:
|
|
84
|
+
failed += 1
|
|
85
|
+
print(" FAIL %s\n %s: %s" % (name, type(error).__name__, error))
|
|
86
|
+
print("\n%d/%d passed" % (len(tests) - failed, len(tests)))
|
|
87
|
+
return 1 if failed else 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
sys.exit(_run_all())
|
|
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
|