discotoolkit 1.3.1__tar.gz → 1.3.3__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.3}/PKG-INFO +14 -15
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/README.md +2 -2
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/CELLiD.py +36 -28
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/__init__.py +1 -1
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/PKG-INFO +14 -15
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/SOURCES.txt +2 -0
- discotoolkit-1.3.3/discotoolkit.egg-info/requires.txt +11 -0
- discotoolkit-1.3.3/requirements.txt +14 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/setup.py +2 -2
- discotoolkit-1.3.3/tests/test_cellid_correlation.py +91 -0
- discotoolkit-1.3.3/tests/test_requirements.py +55 -0
- discotoolkit-1.3.1/discotoolkit.egg-info/requires.txt +0 -12
- discotoolkit-1.3.1/requirements.txt +0 -12
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/MANIFEST.in +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/CellMapper.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/DiscoClass.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/DownloadDiscoData.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GeneSearch.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GetMetadata.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GlobalVariable.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/Utilities.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/dependency_links.txt +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/top_level.txt +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/pyproject.toml +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/setup.cfg +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_docs.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_gene_search.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_metadata_helpers.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_reference_loading.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_server_contract.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_settings.py +0 -0
- {discotoolkit-1.3.1 → discotoolkit-1.3.3}/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.3
|
|
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,18 +11,17 @@ 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<
|
|
15
|
-
Requires-Dist: numpy
|
|
16
|
-
Requires-Dist: scanpy
|
|
17
|
-
Requires-Dist: scipy
|
|
18
|
-
Requires-Dist: joblib
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: seaborn>=0.12
|
|
14
|
+
Requires-Dist: pandas<4,>=1.4.2
|
|
15
|
+
Requires-Dist: numpy<3,>=1.21.6
|
|
16
|
+
Requires-Dist: scanpy<2,>=1.9.3
|
|
17
|
+
Requires-Dist: scipy<2,>=1.10.1
|
|
18
|
+
Requires-Dist: joblib<2,>=1.1.0
|
|
19
|
+
Requires-Dist: requests<3,>=2.28.1
|
|
20
|
+
Requires-Dist: colorcet<4,>=3.0.1
|
|
21
|
+
Requires-Dist: leidenalg<0.14
|
|
22
|
+
Requires-Dist: h5py<4,>=3.8
|
|
23
|
+
Requires-Dist: matplotlib<4,>=3.5
|
|
24
|
+
Requires-Dist: seaborn<0.15,>=0.12
|
|
26
25
|
Dynamic: author
|
|
27
26
|
Dynamic: author-email
|
|
28
27
|
Dynamic: description
|
|
@@ -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.3
|
|
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.3
|
|
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.3
|
|
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,18 +11,17 @@ 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<
|
|
15
|
-
Requires-Dist: numpy
|
|
16
|
-
Requires-Dist: scanpy
|
|
17
|
-
Requires-Dist: scipy
|
|
18
|
-
Requires-Dist: joblib
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: seaborn>=0.12
|
|
14
|
+
Requires-Dist: pandas<4,>=1.4.2
|
|
15
|
+
Requires-Dist: numpy<3,>=1.21.6
|
|
16
|
+
Requires-Dist: scanpy<2,>=1.9.3
|
|
17
|
+
Requires-Dist: scipy<2,>=1.10.1
|
|
18
|
+
Requires-Dist: joblib<2,>=1.1.0
|
|
19
|
+
Requires-Dist: requests<3,>=2.28.1
|
|
20
|
+
Requires-Dist: colorcet<4,>=3.0.1
|
|
21
|
+
Requires-Dist: leidenalg<0.14
|
|
22
|
+
Requires-Dist: h5py<4,>=3.8
|
|
23
|
+
Requires-Dist: matplotlib<4,>=3.5
|
|
24
|
+
Requires-Dist: seaborn<0.15,>=0.12
|
|
26
25
|
Dynamic: author
|
|
27
26
|
Dynamic: author-email
|
|
28
27
|
Dynamic: description
|
|
@@ -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.3
|
|
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,10 +17,12 @@ 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
|
|
23
24
|
tests/test_reference_loading.py
|
|
25
|
+
tests/test_requirements.py
|
|
24
26
|
tests/test_server_contract.py
|
|
25
27
|
tests/test_settings.py
|
|
26
28
|
tests/test_version.py
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Every dependency has an upper limit at the next major version (next minor for 0.x packages), so a new
|
|
2
|
+
# major release cannot break a fresh `pip install discotoolkit`. When one arrives and is wanted: raise the
|
|
3
|
+
# limit, let CI and the Docs build run, release. See "Dependency limits" in RELEASING.md.
|
|
4
|
+
pandas>=1.4.2,<4
|
|
5
|
+
numpy>=1.21.6,<3
|
|
6
|
+
scanpy>=1.9.3,<2
|
|
7
|
+
scipy>=1.10.1,<2
|
|
8
|
+
joblib>=1.1.0,<2
|
|
9
|
+
requests>=2.28.1,<3
|
|
10
|
+
colorcet>=3.0.1,<4
|
|
11
|
+
leidenalg<0.14
|
|
12
|
+
h5py>=3.8,<4
|
|
13
|
+
matplotlib>=3.5,<4
|
|
14
|
+
seaborn>=0.12,<0.15
|
|
@@ -2,11 +2,11 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
# Read the contents of the requirements.txt file
|
|
4
4
|
with open("requirements.txt", "r") as f:
|
|
5
|
-
requirements = f.
|
|
5
|
+
requirements = [line.strip() for line in f if line.strip() and not line.lstrip().startswith("#")]
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name='discotoolkit',
|
|
9
|
-
version="1.3.
|
|
9
|
+
version="1.3.3",
|
|
10
10
|
url='https://disco.bii.a-star.edu.sg/',
|
|
11
11
|
author='Li Mengwei, Rom Uddamvathanak',
|
|
12
12
|
author_email='uddamvathanak_rom@immunol.a-star.edu.sg',
|
|
@@ -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())
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Every dependency in requirements.txt has an upper limit, so a new major release of pandas, numpy and the
|
|
3
|
+
rest cannot break a fresh install. A new dependency without one fails here. See RELEASING.md.
|
|
4
|
+
|
|
5
|
+
python tests/test_requirements.py
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
ROOT = os.path.join(os.path.dirname(__file__), "..")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def requirements():
|
|
15
|
+
with open(os.path.join(ROOT, "requirements.txt"), encoding="utf-8") as handle:
|
|
16
|
+
return [line.strip() for line in handle if line.strip() and not line.lstrip().startswith("#")]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_every_dependency_has_an_upper_limit():
|
|
20
|
+
unlimited = [line for line in requirements() if not re.search(r"<=?\s*\d", line)]
|
|
21
|
+
assert not unlimited, "no upper limit (add <next major): %s" % unlimited
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_the_limits_leave_room_above_the_minimum():
|
|
25
|
+
for line in requirements():
|
|
26
|
+
low = re.search(r">=\s*([\d.]+)", line)
|
|
27
|
+
high = re.search(r"<\s*([\d.]+)", line)
|
|
28
|
+
if low and high:
|
|
29
|
+
as_tuple = lambda text: tuple(int(part) for part in text.split(".")) # noqa: E731
|
|
30
|
+
assert as_tuple(low.group(1)) < as_tuple(high.group(1)), line
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_every_line_is_a_valid_requirement():
|
|
34
|
+
from packaging.requirements import Requirement
|
|
35
|
+
|
|
36
|
+
for line in requirements():
|
|
37
|
+
Requirement(line)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _run_all():
|
|
41
|
+
tests = [(n, f) for n, f in sorted(globals().items()) if n.startswith("test_") and callable(f)]
|
|
42
|
+
failed = 0
|
|
43
|
+
for name, fn in tests:
|
|
44
|
+
try:
|
|
45
|
+
fn()
|
|
46
|
+
print(" PASS %s" % name)
|
|
47
|
+
except Exception as error:
|
|
48
|
+
failed += 1
|
|
49
|
+
print(" FAIL %s\n %s: %s" % (name, type(error).__name__, error))
|
|
50
|
+
print("\n%d/%d passed" % (len(tests) - failed, len(tests)))
|
|
51
|
+
return 1 if failed else 0
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
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
|