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.
Files changed (32) hide show
  1. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/PKG-INFO +14 -15
  2. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/README.md +2 -2
  3. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/CELLiD.py +36 -28
  4. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/__init__.py +1 -1
  5. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/PKG-INFO +14 -15
  6. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/SOURCES.txt +2 -0
  7. discotoolkit-1.3.3/discotoolkit.egg-info/requires.txt +11 -0
  8. discotoolkit-1.3.3/requirements.txt +14 -0
  9. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/setup.py +2 -2
  10. discotoolkit-1.3.3/tests/test_cellid_correlation.py +91 -0
  11. discotoolkit-1.3.3/tests/test_requirements.py +55 -0
  12. discotoolkit-1.3.1/discotoolkit.egg-info/requires.txt +0 -12
  13. discotoolkit-1.3.1/requirements.txt +0 -12
  14. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/MANIFEST.in +0 -0
  15. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/CellMapper.py +0 -0
  16. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/DiscoClass.py +0 -0
  17. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/DownloadDiscoData.py +0 -0
  18. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GeneSearch.py +0 -0
  19. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GetMetadata.py +0 -0
  20. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/GlobalVariable.py +0 -0
  21. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit/Utilities.py +0 -0
  22. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/dependency_links.txt +0 -0
  23. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/discotoolkit.egg-info/top_level.txt +0 -0
  24. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/pyproject.toml +0 -0
  25. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/setup.cfg +0 -0
  26. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_docs.py +0 -0
  27. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_gene_search.py +0 -0
  28. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_metadata_helpers.py +0 -0
  29. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_reference_loading.py +0 -0
  30. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_server_contract.py +0 -0
  31. {discotoolkit-1.3.1 → discotoolkit-1.3.3}/tests/test_settings.py +0 -0
  32. {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.1
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<3,>=1.4.2
15
- Requires-Dist: numpy>=1.21.6
16
- Requires-Dist: scanpy>=1.9.3
17
- Requires-Dist: scipy>=1.10.1
18
- Requires-Dist: joblib>=1.1.0
19
- Requires-Dist: pandarallel>=1.6.5
20
- Requires-Dist: requests>=2.28.1
21
- Requires-Dist: colorcet>=3.0.1
22
- Requires-Dist: leidenalg
23
- Requires-Dist: h5py>=3.8
24
- Requires-Dist: matplotlib>=3.5
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
  [![Documentation](https://img.shields.io/badge/docs-disco.bii.a--star.edu.sg-blue)](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [![Downloads](https://static.pepy.tech/personalized-badge/discotoolkit?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/discotoolkit) [![PyPI version](https://img.shields.io/pypi/v/discotoolkit)](https://pypi.org/project/discotoolkit)
45
44
 
46
- # DISCOtoolkit 1.3.1
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, pandarallel, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
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
  [![Documentation](https://img.shields.io/badge/docs-disco.bii.a--star.edu.sg-blue)](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [![Downloads](https://static.pepy.tech/personalized-badge/discotoolkit?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/discotoolkit) [![PyPI version](https://img.shields.io/pypi/v/discotoolkit)](https://pypi.org/project/discotoolkit)
10
10
 
11
- # DISCOtoolkit 1.3.1
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, pandarallel, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
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
- # nested apply function to compute correlation for each cell type between the user and reference database
251
- def each_ref_correlation(input, ref_data):
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
 
@@ -5,4 +5,4 @@ from .CELLiD import *
5
5
  from .GeneSearch import *
6
6
  from .GlobalVariable import set_server, get_server
7
7
 
8
- __version__ = "1.3.1"
8
+ __version__ = "1.3.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: discotoolkit
3
- Version: 1.3.1
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<3,>=1.4.2
15
- Requires-Dist: numpy>=1.21.6
16
- Requires-Dist: scanpy>=1.9.3
17
- Requires-Dist: scipy>=1.10.1
18
- Requires-Dist: joblib>=1.1.0
19
- Requires-Dist: pandarallel>=1.6.5
20
- Requires-Dist: requests>=2.28.1
21
- Requires-Dist: colorcet>=3.0.1
22
- Requires-Dist: leidenalg
23
- Requires-Dist: h5py>=3.8
24
- Requires-Dist: matplotlib>=3.5
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
  [![Documentation](https://img.shields.io/badge/docs-disco.bii.a--star.edu.sg-blue)](https://disco.bii.a-star.edu.sg/v1/docs/toolkit/guide/) [![Downloads](https://static.pepy.tech/personalized-badge/discotoolkit?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/discotoolkit) [![PyPI version](https://img.shields.io/pypi/v/discotoolkit)](https://pypi.org/project/discotoolkit)
45
44
 
46
- # DISCOtoolkit 1.3.1
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, pandarallel, requests, colorcet, leidenalg, h5py, matplotlib, seaborn.
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,11 @@
1
+ pandas<4,>=1.4.2
2
+ numpy<3,>=1.21.6
3
+ scanpy<2,>=1.9.3
4
+ scipy<2,>=1.10.1
5
+ joblib<2,>=1.1.0
6
+ requests<3,>=2.28.1
7
+ colorcet<4,>=3.0.1
8
+ leidenalg<0.14
9
+ h5py<4,>=3.8
10
+ matplotlib<4,>=3.5
11
+ seaborn<0.15,>=0.12
@@ -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.read().splitlines()
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.1",
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())
@@ -1,12 +0,0 @@
1
- pandas<3,>=1.4.2
2
- numpy>=1.21.6
3
- scanpy>=1.9.3
4
- scipy>=1.10.1
5
- joblib>=1.1.0
6
- pandarallel>=1.6.5
7
- requests>=2.28.1
8
- colorcet>=3.0.1
9
- leidenalg
10
- h5py>=3.8
11
- matplotlib>=3.5
12
- seaborn>=0.12
@@ -1,12 +0,0 @@
1
- pandas>=1.4.2,<3
2
- numpy>=1.21.6
3
- scanpy>=1.9.3
4
- scipy>=1.10.1
5
- joblib>=1.1.0
6
- pandarallel>=1.6.5
7
- requests>=2.28.1
8
- colorcet>=3.0.1
9
- leidenalg
10
- h5py>=3.8
11
- matplotlib>=3.5
12
- seaborn>=0.12
File without changes
File without changes