rectanglepy 0.4.7__tar.gz → 0.5.0__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 (56) hide show
  1. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.bumpversion.cfg +1 -1
  2. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/PKG-INFO +9 -6
  3. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/README.md +1 -1
  4. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/Makefile +3 -0
  5. rectanglepy-0.5.0/docs/api.md +15 -0
  6. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/conf.py +1 -11
  7. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/contributing.md +0 -74
  8. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/notebooks/example.ipynb +1 -29
  9. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/pyproject.toml +7 -4
  10. rectanglepy-0.5.0/src/rectanglepy/__init__.py +8 -0
  11. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/pp/create_signature.py +0 -25
  12. rectanglepy-0.5.0/src/rectanglepy/rectangle.py +112 -0
  13. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/test_pp.py +0 -34
  14. rectanglepy-0.4.7/docs/api.md +0 -17
  15. rectanglepy-0.4.7/src/rectanglepy/__init__.py +0 -8
  16. rectanglepy-0.4.7/src/rectanglepy/rectangle.py +0 -222
  17. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.cruft.json +0 -0
  18. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.editorconfig +0 -0
  19. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  20. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  21. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  22. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  23. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/workflows/build.yaml +0 -0
  24. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/workflows/release.yaml +0 -0
  25. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/workflows/release_testpypi.yaml +0 -0
  26. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.github/workflows/test.yaml +0 -0
  27. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.gitignore +0 -0
  28. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.pre-commit-config.yaml +0 -0
  29. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/.readthedocs.yaml +0 -0
  30. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/CHANGELOG.md +0 -0
  31. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/LICENSE +0 -0
  32. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/_static/.gitkeep +0 -0
  33. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/_templates/.gitkeep +0 -0
  34. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/_templates/autosummary/class.rst +0 -0
  35. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/changelog.md +0 -0
  36. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/extensions/typed_returns.py +0 -0
  37. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/index.md +0 -0
  38. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/make.bat +0 -0
  39. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/references.bib +0 -0
  40. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/docs/references.md +0 -0
  41. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/data/hao1_annotations_small.zip +0 -0
  42. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/data/hao1_counts_small.zip +0 -0
  43. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/data/small_fino_bulks.zip +0 -0
  44. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/pp/__init__.py +0 -0
  45. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/pp/rectangle_signature.py +0 -0
  46. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/tl/__init__.py +0 -0
  47. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/src/rectanglepy/tl/deconvolution.py +0 -0
  48. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/TIL10_signature.txt +0 -0
  49. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/bulk_small.csv +0 -0
  50. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/cell_annotations_small.txt +0 -0
  51. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/quanTIseq_SimRNAseq_mixture_smaller.csv +0 -0
  52. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt +0 -0
  53. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/sc_object_small.csv +0 -0
  54. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/data/signature_hao1.csv +0 -0
  55. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/test_rectangle.py +0 -0
  56. {rectanglepy-0.4.7 → rectanglepy-0.5.0}/tests/test_tl.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.4.7
2
+ current_version = 0.5.0
3
3
  tag = True
4
4
  commit = True
5
5
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: rectanglepy
3
- Version: 0.4.7
3
+ Version: 0.5.0
4
4
  Summary: Hierarchical deconvolution of bulk transcriptomics
5
5
  Project-URL: Documentation, https://rectanglepy.readthedocs.io/
6
6
  Project-URL: Source, https://github.com/ComputationalBiomedicineGroup/Rectangle
@@ -28,26 +28,29 @@ License: MIT License
28
28
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
29
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
30
  SOFTWARE.
31
+ License-File: LICENSE
31
32
  Requires-Python: >=3.10
32
33
  Requires-Dist: anndata<0.10.9,>=0.8.0
33
34
  Requires-Dist: loguru
34
35
  Requires-Dist: numpy<2.0.0,>=1.0.0
35
36
  Requires-Dist: pydeseq2==0.4.11
36
37
  Requires-Dist: quadprog==0.1.12
38
+ Requires-Dist: scipy==1.13.0
37
39
  Requires-Dist: statsmodels>=0.14.1
38
40
  Provides-Extra: dev
39
41
  Requires-Dist: bump2version; extra == 'dev'
40
42
  Requires-Dist: pre-commit; extra == 'dev'
41
43
  Requires-Dist: twine>=4.0.2; extra == 'dev'
42
44
  Provides-Extra: doc
45
+ Requires-Dist: furo; extra == 'doc'
43
46
  Requires-Dist: ipykernel; extra == 'doc'
44
47
  Requires-Dist: ipython; extra == 'doc'
45
48
  Requires-Dist: myst-nb; extra == 'doc'
49
+ Requires-Dist: sphinx; extra == 'doc'
46
50
  Requires-Dist: sphinx-autodoc-typehints; extra == 'doc'
47
- Requires-Dist: sphinx-book-theme>=1.0.0; extra == 'doc'
51
+ Requires-Dist: sphinx-book-theme; extra == 'doc'
48
52
  Requires-Dist: sphinx-copybutton; extra == 'doc'
49
- Requires-Dist: sphinx>=4; extra == 'doc'
50
- Requires-Dist: sphinxcontrib-bibtex>=1.0.0; extra == 'doc'
53
+ Requires-Dist: sphinxcontrib-bibtex; extra == 'doc'
51
54
  Provides-Extra: test
52
55
  Requires-Dist: pytest; extra == 'test'
53
56
  Description-Content-Type: text/markdown
@@ -79,7 +82,7 @@ Python installed, we recommend installing [Mambaforge](https://github.com/conda-
79
82
 
80
83
  How to install Rectangle:
81
84
 
82
- Install the latest release of `Rectangle` from `PyPI <https://pypi.org/project/rectanglepy/>`:
85
+ Install the latest release of `Rectangle` from `PyPI` <https://pypi.org/project/rectanglepy/>:
83
86
 
84
87
  ```bash
85
88
  pip install rectanglepy
@@ -25,7 +25,7 @@ Python installed, we recommend installing [Mambaforge](https://github.com/conda-
25
25
 
26
26
  How to install Rectangle:
27
27
 
28
- Install the latest release of `Rectangle` from `PyPI <https://pypi.org/project/rectanglepy/>`:
28
+ Install the latest release of `Rectangle` from `PyPI` <https://pypi.org/project/rectanglepy/>:
29
29
 
30
30
  ```bash
31
31
  pip install rectanglepy
@@ -18,3 +18,6 @@ help:
18
18
  # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19
19
  %: Makefile
20
20
  @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21
+
22
+ html:
23
+ @$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,15 @@
1
+ # API
2
+
3
+ ## Rectangle
4
+
5
+ ```{eval-rst}
6
+ .. currentmodule:: rectanglepy
7
+
8
+ .. autosummary::
9
+ :toctree: generated
10
+
11
+ rectangle
12
+ pp.build_rectangle_signatures
13
+ tl.deconvolution
14
+ pp.RectangleSignatureResult
15
+ ```
@@ -104,7 +104,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints"]
104
104
  # The theme to use for HTML and HTML Help pages. See the documentation for
105
105
  # a list of builtin themes.
106
106
  #
107
- html_theme = "sphinx_book_theme"
107
+ html_theme = "furo"
108
108
  html_static_path = ["_static"]
109
109
  html_title = "rectangle"
110
110
 
@@ -114,16 +114,6 @@ html_theme_options = {
114
114
  "path_to_docs": "docs/",
115
115
  }
116
116
 
117
- pygments_style = "emacs"
118
-
119
- nitpick_ignore = [
120
- # If building the documentation fails because of a missing link that is outside your control,
121
- # you can add an exception to this list.
122
- # ("py:class", "igraph.Graph"),
123
- ]
124
-
125
- print("Pygments style:", pygments_style)
126
-
127
117
 
128
118
  def setup(app):
129
119
  """App setup hook."""
@@ -7,48 +7,6 @@ information to get you started on contributing.
7
7
  We assume that you are already familiar with git and with making pull requests on GitHub. If not, please refer
8
8
  to the [scanpy developer guide][].
9
9
 
10
- ## Installing dev dependencies
11
-
12
- In addition to the packages needed to _use_ this package, you need additional python packages to _run tests_ and _build
13
- the documentation_. It's easy to install them using `pip`:
14
-
15
- ```bash
16
- cd Rectangle
17
- pip install -e ".[dev,test,doc]"
18
- ```
19
-
20
- ## Code-style
21
-
22
- This template uses [pre-commit][] to enforce consistent code-styles. On every commit, pre-commit checks will either
23
- automatically fix issues with the code, or raise an error message. See [pre-commit checks](template_usage.md#pre-commit-checks) for
24
- a full list of checks enabled for this repository.
25
-
26
- To enable pre-commit locally, simply run
27
-
28
- ```bash
29
- pre-commit install
30
- ```
31
-
32
- in the root of the repository. Pre-commit will automatically download all dependencies when it is run for the first time.
33
-
34
- Alternatively, you can rely on the [pre-commit.ci][] service enabled on GitHub. If you didn't run `pre-commit` before
35
- pushing changes to GitHub it will automatically commit fixes to your pull request, or show an error message.
36
-
37
- If pre-commit.ci added a commit on a branch you still have been working on locally, simply use
38
-
39
- ```bash
40
- git pull --rebase
41
- ```
42
-
43
- to integrate the changes into yours.
44
- While the [pre-commit.ci][] is useful, we strongly encourage installing and running pre-commit locally first to understand its usage.
45
-
46
- Finally, most editors have an _autoformat on save_ feature. Consider enabling this option for [black][black-editors]
47
- and [prettier][prettier-editors].
48
-
49
- [black-editors]: https://black.readthedocs.io/en/stable/integrations/editors.html
50
- [prettier-editors]: https://prettier.io/docs/en/editors.html
51
-
52
10
  ## Writing tests
53
11
 
54
12
  ```{note}
@@ -102,38 +60,6 @@ to publish the created tag on GitHub.
102
60
 
103
61
  [bump2version]: https://github.com/c4urself/bump2version
104
62
 
105
- ### Building and publishing the package on PyPI
106
-
107
- Python packages are not distributed as source code, but as _distributions_. The most common distribution format is the so-called _wheel_. To build a _wheel_, run
108
-
109
- ```bash
110
- python -m build
111
- ```
112
-
113
- This command creates a _source archive_ and a _wheel_, which are required for publishing your package to [PyPI][]. These files are created directly in the root of the repository.
114
-
115
- Before uploading them to [PyPI][] you can check that your _distribution_ is valid by running:
116
-
117
- ```bash
118
- twine check dist/*
119
- ```
120
-
121
- and finally publishing it with:
122
-
123
- ```bash
124
- twine upload dist/*
125
- ```
126
-
127
- Provide your username and password when requested and then go check out your package on [PyPI][]!
128
-
129
- For more information, follow the [Python packaging tutorial][].
130
-
131
- It is possible to automate this with GitHub actions, see also [this feature request][pypi-feature-request]
132
- in the cookiecutter-scverse template.
133
-
134
- [python packaging tutorial]: https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives
135
- [pypi-feature-request]: https://github.com/scverse/cookiecutter-scverse/issues/88
136
-
137
63
  ## Writing documentation
138
64
 
139
65
  Please write documentation for new or changed features and use-cases. This project uses [sphinx][] with the following features:
@@ -200,39 +200,11 @@
200
200
  },
201
201
  {
202
202
  "cell_type": "markdown",
203
- "source": "signature_result is a [`RectangleSignatureResult`](../generated/rectanglepy.pp.RectangleSignatureResult.rst) object. ",
203
+ "source": "signature_result is a [`RectangleSignatureResult`](../generated/rectanglepy.pp.RectangleSignatureResult.rst) object.",
204
204
  "metadata": {
205
205
  "collapsed": false
206
206
  }
207
207
  },
208
- {
209
- "cell_type": "markdown",
210
- "source": "## Running Rectangle in Consensus mode",
211
- "metadata": {
212
- "collapsed": false
213
- }
214
- },
215
- {
216
- "cell_type": "markdown",
217
- "source": "For some scRNA-seq datatasets it may be beneficial to run rectangle in consensus mode. In this function we run the rectangle algorithm multiple times (`consensus_runs`), where on each iteration we sample `sample_size` cells of each cell type. The final cell type proportions are the median of the proportions estimated in each run.",
218
- "metadata": {
219
- "collapsed": false
220
- }
221
- },
222
- {
223
- "cell_type": "code",
224
- "outputs": [],
225
- "source": "estimations, signature_result, consensus_result = rectangle.rectangle_consens(sc_adata, bulks, consensus_runs=5, sample_size=1500)",
226
- "metadata": {
227
- "collapsed": false
228
- },
229
- "execution_count": null
230
- },
231
- {
232
- "metadata": {},
233
- "cell_type": "markdown",
234
- "source": "signature_result holds the signature result([`RectangleSignatureResult`](../generated/rectanglepy.pp.RectangleSignatureResult.rst)) for the most recent consensus run, while consensus_result is a [`ConsensusResult`](../generated/rectanglepy.ConsensusResult.rst) object that holds the results of all the runs."
235
- },
236
208
  {
237
209
  "cell_type": "markdown",
238
210
  "source": [
@@ -4,7 +4,7 @@ requires = ["hatchling"]
4
4
 
5
5
  [project]
6
6
  name = "rectanglepy"
7
- version = "0.4.7"
7
+ version = "0.5.0"
8
8
  description = "Hierarchical deconvolution of bulk transcriptomics"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -20,11 +20,13 @@ urls.Source = "https://github.com/ComputationalBiomedicineGroup/Rectangle"
20
20
  urls.Home-page = "https://github.com/ComputationalBiomedicineGroup/Rectangle"
21
21
  dependencies = [
22
22
  "pydeseq2==0.4.11",
23
+ "scipy==1.13.0",
23
24
  "quadprog==0.1.12",
24
25
  "loguru",
25
26
  "numpy>=1.0.0,<2.0.0",
26
27
  "anndata>=0.8.0,<0.10.9",
27
28
  "statsmodels>=0.14.1"
29
+
28
30
  ]
29
31
 
30
32
  [project.optional-dependencies]
@@ -34,15 +36,16 @@ dev = [
34
36
  "twine>=4.0.2"
35
37
  ]
36
38
  doc = [
37
- "sphinx>=4",
38
- "sphinx-book-theme>=1.0.0",
39
+ "sphinx",
40
+ "sphinx-book-theme",
39
41
  "myst-nb",
40
- "sphinxcontrib-bibtex>=1.0.0",
42
+ "sphinxcontrib-bibtex",
41
43
  "sphinx-autodoc-typehints",
42
44
  # For notebooks
43
45
  "ipykernel",
44
46
  "ipython",
45
47
  "sphinx-copybutton",
48
+ "furo",
46
49
  ]
47
50
  test = [
48
51
  "pytest",
@@ -0,0 +1,8 @@
1
+ from importlib.metadata import version
2
+
3
+ from . import pp, tl
4
+ from .rectangle import load_tutorial_data, rectangle
5
+
6
+ __all__ = ["pp", "tl", "load_tutorial_data", "rectangle"]
7
+
8
+ __version__ = version("rectanglepy")
@@ -285,10 +285,7 @@ def build_rectangle_signatures(
285
285
  raw: bool = False,
286
286
  p=0.015,
287
287
  lfc=1.5,
288
- subsample: bool = False,
289
- sample_size: int = 1500,
290
288
  n_cpus: int = None,
291
- run: int = 0,
292
289
  gene_expression_threshold=0.5,
293
290
  ) -> RectangleSignatureResult:
294
291
  r"""Builds rectangle signatures based on single-cell count data and annotations.
@@ -305,10 +302,6 @@ def build_rectangle_signatures(
305
302
  The Anndata layer to use for the single-cell data. Defaults to None.
306
303
  raw
307
304
  A flag indicating whether to use the raw Anndata data. Defaults to False.
308
- subsample : bool
309
- A flag indicating whether to balance the single-cell data. Defaults to False.
310
- sample_size : int
311
- The number of cells to balance the single-cell data to. Defaults to 1500. If cell number is less than this number it takes the original number of cells.
312
305
  optimize_cutoffs
313
306
  Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch. Defaults to True.
314
307
  p
@@ -317,8 +310,6 @@ def build_rectangle_signatures(
317
310
  The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
318
311
  n_cpus
319
312
  The number of cpus to use for the DE analysis. Defaults to the number of cpus available.
320
- run
321
- The consensus run number for the analysis. Defaults to 0.
322
313
  gene_expression_threshold
323
314
  The gene expression threshold for the DE analysis. How many cells need to express a gene to be considered in DGE
324
315
 
@@ -336,10 +327,6 @@ def build_rectangle_signatures(
336
327
  logger.info(f"Using {len(genes)} common genes between bulks and single-cell data")
337
328
  adata = adata[:, genes]
338
329
 
339
- if subsample:
340
- annotations = _even(annotations, sample_size, run)
341
- adata = adata[annotations.index]
342
-
343
330
  if layer is not None:
344
331
  sc_counts = adata.layers[layer]
345
332
  elif raw:
@@ -509,15 +496,3 @@ def _reduce_to_common_genes(bulks: pd.DataFrame, sc_data: pd.DataFrame):
509
496
  sc_data = sc_data.loc[genes].sort_index()
510
497
  bulks = bulks.loc[genes].sort_index()
511
498
  return bulks, sc_data
512
-
513
-
514
- def _even(annotations: pd.Series, number: int, run=0) -> pd.Series:
515
- np.random.seed(run)
516
- assert number > 0, "Number of cells must be greater than 0"
517
- annotation_counts = annotations.value_counts()
518
- selected_cells = []
519
- for annotation in annotation_counts.index:
520
- cells = annotations[annotations == annotation].index
521
- cells = np.random.choice(cells, min(number, len(cells)), replace=False)
522
- selected_cells.extend(cells)
523
- return annotations.loc[selected_cells]
@@ -0,0 +1,112 @@
1
+ import pandas as pd
2
+ from anndata import AnnData
3
+ from loguru import logger
4
+ from pandas import DataFrame
5
+ from pkg_resources import resource_stream
6
+
7
+ from .pp import RectangleSignatureResult, build_rectangle_signatures
8
+ from .tl import deconvolution
9
+
10
+
11
+ def rectangle(
12
+ adata: AnnData,
13
+ bulks: DataFrame,
14
+ cell_type_col: str = "cell_type",
15
+ *,
16
+ layer: str = None,
17
+ raw: bool = False,
18
+ correct_mrna_bias: bool = True,
19
+ optimize_cutoffs=True,
20
+ p=0.015,
21
+ lfc=1.5,
22
+ n_cpus: int = None,
23
+ gene_expression_threshold=0.5,
24
+ ) -> tuple[DataFrame, RectangleSignatureResult]:
25
+ r"""All in one deconvolution method. Creates signatures and deconvolutes the bulk data. Has options for subsampling and consensus runs.
26
+
27
+ Parameters
28
+ ----------
29
+ adata
30
+ The single-cell count data as a DataFrame. DataFrame must have the genes as index and cell identifier as columns. Each entry should be in raw counts.
31
+ bulks
32
+ The bulk data as a DataFrame. DataFrame must have the bulk identifier as index and the genes as columns. Each entry should be in transcripts per million (TPM).
33
+ cell_type_col
34
+ The annotations corresponding to the single-cell count data. Series data should have the cell identifier as index and the annotations as values.
35
+ layer
36
+ The Anndata layer to use for the single-cell data.
37
+ raw
38
+ A flag indicating whether to use the raw Anndata data.
39
+ optimize_cutoffs
40
+ Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
41
+ p
42
+ The p-value threshold for the DE analysis (only used if optimize_cutoffs is False).
43
+ lfc
44
+ The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
45
+ n_cpus
46
+ The number of cpus to use for the DE analysis. None value takes all cpus available.
47
+ correct_mrna_bias : bool
48
+ A flag indicating whether to correct for mRNA bias. Defaults to True.
49
+ gene_expression_threshold : float
50
+ The threshold for gene expression. Genes with expression below this threshold are removed from the analysis.
51
+
52
+ Returns
53
+ -------
54
+ DataFrame : The estimated cell fractions.
55
+ RectangleSignatureResult : The result of the rectangle signature analysis.
56
+ """
57
+ assert isinstance(adata, AnnData), "adata must be an AnnData object"
58
+ assert isinstance(bulks, DataFrame), "bulks must be a DataFrame"
59
+
60
+ signatures = build_rectangle_signatures(
61
+ adata,
62
+ cell_type_col,
63
+ bulks=bulks,
64
+ optimize_cutoffs=optimize_cutoffs,
65
+ layer=layer,
66
+ raw=raw,
67
+ p=p,
68
+ lfc=lfc,
69
+ n_cpus=n_cpus,
70
+ gene_expression_threshold=gene_expression_threshold,
71
+ )
72
+
73
+ estimations = deconvolution(signatures, bulks, correct_mrna_bias, n_cpus)
74
+
75
+ if "Unknown" in estimations.columns:
76
+ try:
77
+ unkn_gene_corr = _genes_linked_to_unkn(bulks, estimations["Unknown"])
78
+ except Exception as e:
79
+ logger.warning(f"Could not calculate gene correlation with unknown cell type: {e}")
80
+ unkn_gene_corr = None
81
+ else:
82
+ unkn_gene_corr = None
83
+ signatures.unkn_gene_corr = unkn_gene_corr
84
+
85
+ return estimations, signatures
86
+
87
+
88
+ def load_tutorial_data() -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
89
+ """Loads the single-cell count data, annotations, and bulk data from the tutorial.
90
+
91
+ Returns
92
+ -------
93
+ The single-cell count data, annotations, and bulk data.
94
+ """
95
+ with resource_stream(__name__, "data/hao1_annotations_small.zip") as annotations_file:
96
+ annotations = pd.read_csv(annotations_file, index_col=0, compression="zip")["0"]
97
+
98
+ with resource_stream(__name__, "data/hao1_counts_small.zip") as counts_file:
99
+ sc_counts = pd.read_csv(counts_file, index_col=0, compression="zip").astype("int")
100
+
101
+ with resource_stream(__name__, "data/small_fino_bulks.zip") as bulks_file:
102
+ bulks = pd.read_csv(bulks_file, index_col=0, compression="zip")
103
+
104
+ return sc_counts.T, annotations, bulks.T
105
+
106
+
107
+ def _genes_linked_to_unkn(bulks: DataFrame, unkn_fractions: pd.Series):
108
+ genes = bulks.columns.drop_duplicates()
109
+ corr = []
110
+ for gene in genes:
111
+ corr.append(unkn_fractions.corr(bulks.loc[:, gene]))
112
+ return pd.Series(corr, index=genes).sort_values(ascending=False)
@@ -16,7 +16,6 @@ from rectanglepy.pp.create_signature import (
16
16
  _create_linkage_matrix,
17
17
  _create_pseudo_count_sig,
18
18
  _de_analysis,
19
- _even,
20
19
  _generate_pseudo_bulks,
21
20
  _get_fcluster_assignments,
22
21
  _run_deseq2,
@@ -209,39 +208,6 @@ def test_de_analysis(small_data):
209
208
  assert len(r2) == 3
210
209
 
211
210
 
212
- def test_even(small_data):
213
- sc_data, annotations, _ = small_data
214
- even_annotation = _even(annotations, 20)
215
- assert len(even_annotation) == 51
216
- counts = annotations.loc[even_annotation.index].value_counts()
217
- assert counts.equals(pd.Series({"T cell CD4": 20, "T cell CD8": 20, "NK cell": 11}))
218
-
219
- even_sc_data = sc_data.loc[:, _even(annotations, 100).index]
220
-
221
- assert round(even_sc_data.sum().sum(), 3) == round(sc_data.sum().sum(), 3)
222
-
223
-
224
- def test_build_rectangle_signatures_even(small_data):
225
- sc_counts, annotations, bulk = small_data
226
- sc_counts = sc_counts.astype("int")
227
- adata = AnnData(sc_counts.T, obs=annotations.to_frame(name="cell_type"))
228
- results_even = build_rectangle_signatures(
229
- adata,
230
- "cell_type",
231
- bulks=bulk.T,
232
- p=0.5,
233
- lfc=0.1,
234
- optimize_cutoffs=False,
235
- subsample=True,
236
- sample_size=1000,
237
- )
238
- results_uneven = build_rectangle_signatures(
239
- adata, "cell_type", bulks=bulk.T, p=0.5, lfc=0.1, optimize_cutoffs=False
240
- )
241
-
242
- assert results_even.bias_factors.equals(results_uneven.bias_factors)
243
-
244
-
245
211
  def test_create_bootstrap_signature(small_data):
246
212
  bootstraps_per_cell = 7
247
213
  sc_counts, annotations, bulk = small_data
@@ -1,17 +0,0 @@
1
- # API
2
-
3
- ## Rectangle
4
-
5
- ```{eval-rst}
6
- .. currentmodule:: rectanglepy
7
-
8
- .. autosummary::
9
- :toctree: generated
10
-
11
- rectanglepy.rectangle
12
- rectanglepy.rectangle_consens
13
- rectanglepy.pp.build_rectangle_signatures
14
- rectanglepy.tl.deconvolution
15
- rectanglepy.pp.RectangleSignatureResult
16
- rectanglepy.ConsensusResult
17
- ```
@@ -1,8 +0,0 @@
1
- from importlib.metadata import version
2
-
3
- from . import pp, tl
4
- from .rectangle import ConsensusResult, load_tutorial_data, rectangle, rectangle_consens
5
-
6
- __all__ = ["pp", "tl", "load_tutorial_data", "rectangle", "rectangle_consens", "ConsensusResult"]
7
-
8
- __version__ = version("rectanglepy")
@@ -1,222 +0,0 @@
1
- import pandas as pd
2
- from anndata import AnnData
3
- from loguru import logger
4
- from pandas import DataFrame
5
- from pkg_resources import resource_stream
6
-
7
- from .pp import RectangleSignatureResult, build_rectangle_signatures
8
- from .tl import deconvolution
9
-
10
-
11
- class ConsensusResult:
12
- """A class used to represent the consensus result of the rectangle_consens function.
13
-
14
- Parameters
15
- ----------
16
- estimations
17
- A list of DataFrame objects representing the estimations from each consensus run.
18
- rectangle_signature_results
19
- A list of RectangleSignatureResult objects representing the rectangle signature results from each consensus run.
20
- """
21
-
22
- def __init__(self, estimations: list[DataFrame], rectangle_signature_results: list[RectangleSignatureResult]):
23
- self.estimations = estimations
24
- self.rectangle_signature_results = rectangle_signature_results
25
-
26
-
27
- def rectangle_consens(
28
- adata: AnnData,
29
- bulks: DataFrame,
30
- cell_type_col: str = "cell_type",
31
- *,
32
- layer: str = None,
33
- raw: bool = False,
34
- subsample: bool = True,
35
- sample_size: int = 1500,
36
- consensus_runs: int = 5,
37
- correct_mrna_bias: bool = True,
38
- optimize_cutoffs=True,
39
- p=0.015,
40
- lfc=1.5,
41
- n_cpus: int = None,
42
- gene_expression_threshold=0.5,
43
- ) -> tuple[DataFrame, RectangleSignatureResult, ConsensusResult]:
44
- r"""All in one deconvolution method. Creates signatures and deconvolutes the bulk data. Has options for subsampling and consensus runs.
45
-
46
- Parameters
47
- ----------
48
- adata
49
- The single-cell count data as a DataFrame. DataFrame must have the genes as index and cell identifier as columns. Each entry should be in raw counts.
50
- bulks
51
- The bulk data as a DataFrame. DataFrame must have the bulk identifier as index and the genes as columns. Each entry should be in transcripts per million (TPM).
52
- cell_type_col
53
- The annotations corresponding to the single-cell count data. Series data should have the cell identifier as index and the annotations as values.
54
- layer
55
- The Anndata layer to use for the single-cell data. Defaults to None.
56
- raw
57
- A flag indicating whether to use the raw Anndata data. Defaults to False.
58
- subsample : bool
59
- A flag indicating whether to balance the single-cell data.
60
- sample_size : int
61
- The number of cells to balance the single-cell data to. If cell number is less than this number it takes the original number of cells.
62
- consensus_runs : int
63
- The number of consensus runs to perform. Consensus runs are performed by subsampling the single-cell data and running the analysis multiple times. The results are then aggregated.
64
- optimize_cutoffs
65
- Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
66
- p
67
- The p-value threshold for the DE analysis (only used if optimize_cutoffs is False).
68
- lfc
69
- The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
70
- n_cpus
71
- The number of cpus to use for the DE analysis. None value takes all cpus available.
72
- correct_mrna_bias : bool
73
- A flag indicating whether to correct for mRNA bias. Defaults to True.
74
- gene_expression_threshold : float
75
- The threshold for gene expression. Genes with expression below this threshold are removed from the analysis.
76
-
77
- Returns
78
- -------
79
- DataFrame : The estimated cell fractions consens.
80
- RectangleSignatureResult : The result of the last consensus run.
81
- ConsensusResult : Estimations and rectangle signature results for each consensus run.
82
- """
83
- assert isinstance(adata, AnnData), "adata must be an AnnData object"
84
- assert isinstance(bulks, DataFrame), "bulks must be a DataFrame"
85
-
86
- if consensus_runs > 1:
87
- logger.info(f"Running {consensus_runs} consensus runs with subsample size {sample_size}")
88
- subsample = True
89
-
90
- estimations = []
91
- rectangle_signature_results = []
92
- most_recent_signatures = None
93
-
94
- for i in range(consensus_runs):
95
- logger.info(f"Running consensus run {i + 1} of {consensus_runs}")
96
- signatures = build_rectangle_signatures(
97
- adata,
98
- cell_type_col,
99
- bulks=bulks,
100
- optimize_cutoffs=optimize_cutoffs,
101
- layer=layer,
102
- raw=raw,
103
- p=p,
104
- lfc=lfc,
105
- n_cpus=n_cpus,
106
- subsample=subsample,
107
- sample_size=sample_size,
108
- run=i,
109
- gene_expression_threshold=gene_expression_threshold,
110
- )
111
- most_recent_signatures = signatures
112
- cell_fractions = deconvolution(signatures, bulks, correct_mrna_bias, n_cpus)
113
- estimations.append(cell_fractions)
114
- if "Unknown" in cell_fractions.columns:
115
- try:
116
- unkn_gene_corr = _genes_linked_to_unkn(bulks, cell_fractions["Unknown"])
117
- except Exception as e:
118
- logger.warning(f"Could not calculate gene correlation with unknown cell type: {e}")
119
- unkn_gene_corr = None
120
- else:
121
- unkn_gene_corr = None
122
- signatures.unkn_gene_corr = unkn_gene_corr
123
- rectangle_signature_results.append(signatures)
124
- consensus_estimations = pd.concat(estimations).groupby(level=0).median()
125
-
126
- # normalize the estimations to 1, needed for the consensus
127
- consensus_estimations = consensus_estimations.div(consensus_estimations.sum(axis=1), axis=0)
128
- consensus_estimations[consensus_estimations < 0] = 0
129
- consensus_results = ConsensusResult(estimations, rectangle_signature_results)
130
- return consensus_estimations, most_recent_signatures, consensus_results
131
-
132
-
133
- def rectangle(
134
- adata: AnnData,
135
- bulks: DataFrame,
136
- cell_type_col: str = "cell_type",
137
- *,
138
- layer: str = None,
139
- raw: bool = False,
140
- correct_mrna_bias: bool = True,
141
- optimize_cutoffs=True,
142
- p=0.015,
143
- lfc=1.5,
144
- n_cpus: int = None,
145
- gene_expression_threshold=0.5,
146
- ) -> tuple[DataFrame, RectangleSignatureResult]:
147
- r"""All in one deconvolution method. Creates signatures and deconvolutes the bulk data. Has options for subsampling and consensus runs.
148
-
149
- Parameters
150
- ----------
151
- adata
152
- The single-cell count data as a DataFrame. DataFrame must have the genes as index and cell identifier as columns. Each entry should be in raw counts.
153
- bulks
154
- The bulk data as a DataFrame. DataFrame must have the bulk identifier as index and the genes as columns. Each entry should be in transcripts per million (TPM).
155
- cell_type_col
156
- The annotations corresponding to the single-cell count data. Series data should have the cell identifier as index and the annotations as values.
157
- layer
158
- The Anndata layer to use for the single-cell data.
159
- raw
160
- A flag indicating whether to use the raw Anndata data.
161
- optimize_cutoffs
162
- Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
163
- p
164
- The p-value threshold for the DE analysis (only used if optimize_cutoffs is False).
165
- lfc
166
- The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
167
- n_cpus
168
- The number of cpus to use for the DE analysis. None value takes all cpus available.
169
- correct_mrna_bias : bool
170
- A flag indicating whether to correct for mRNA bias. Defaults to True.
171
- gene_expression_threshold : float
172
- The threshold for gene expression. Genes with expression below this threshold are removed from the analysis.
173
-
174
- Returns
175
- -------
176
- DataFrame : The estimated cell fractions.
177
- RectangleSignatureResult : The result of the rectangle signature analysis.
178
- """
179
- estimations, signatures, _ = rectangle_consens(
180
- adata,
181
- bulks,
182
- cell_type_col,
183
- layer=layer,
184
- raw=raw,
185
- subsample=False,
186
- sample_size=-1,
187
- consensus_runs=1,
188
- correct_mrna_bias=correct_mrna_bias,
189
- optimize_cutoffs=optimize_cutoffs,
190
- p=p,
191
- lfc=lfc,
192
- n_cpus=n_cpus,
193
- gene_expression_threshold=gene_expression_threshold,
194
- )
195
- return estimations, signatures
196
-
197
-
198
- def load_tutorial_data() -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
199
- """Loads the single-cell count data, annotations, and bulk data from the tutorial.
200
-
201
- Returns
202
- -------
203
- The single-cell count data, annotations, and bulk data.
204
- """
205
- with resource_stream(__name__, "data/hao1_annotations_small.zip") as annotations_file:
206
- annotations = pd.read_csv(annotations_file, index_col=0, compression="zip")["0"]
207
-
208
- with resource_stream(__name__, "data/hao1_counts_small.zip") as counts_file:
209
- sc_counts = pd.read_csv(counts_file, index_col=0, compression="zip").astype("int")
210
-
211
- with resource_stream(__name__, "data/small_fino_bulks.zip") as bulks_file:
212
- bulks = pd.read_csv(bulks_file, index_col=0, compression="zip")
213
-
214
- return sc_counts.T, annotations, bulks.T
215
-
216
-
217
- def _genes_linked_to_unkn(bulks: DataFrame, unkn_fractions: pd.Series):
218
- genes = bulks.columns.drop_duplicates()
219
- corr = []
220
- for gene in genes:
221
- corr.append(unkn_fractions.corr(bulks.loc[:, gene]))
222
- return pd.Series(corr, index=genes).sort_values(ascending=False)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes