rectanglepy 0.1.3__tar.gz → 0.1.7__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.
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.bumpversion.cfg +1 -1
- rectanglepy-0.1.7/.github/workflows/release_testpypi.yaml +44 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/CHANGELOG.md +13 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/PKG-INFO +2 -1
- rectanglepy-0.1.7/docs/api.md +17 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/notebooks/example.ipynb +14 -13
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/pyproject.toml +2 -1
- rectanglepy-0.1.7/src/rectanglepy/__init__.py +8 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/pp/create_signature.py +15 -8
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/pp/rectangle_signature.py +3 -16
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/rectangle.py +97 -15
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/tl/deconvolution.py +8 -1
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/test_pp.py +1 -1
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/test_rectangle.py +13 -2
- rectanglepy-0.1.3/docs/api.md +0 -15
- rectanglepy-0.1.3/src/rectanglepy/__init__.py +0 -8
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.cruft.json +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.editorconfig +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/workflows/build.yaml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/workflows/release.yaml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.github/workflows/test.yaml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.gitignore +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.pre-commit-config.yaml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/.readthedocs.yaml +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/LICENSE +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/README.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/Makefile +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/_static/.gitkeep +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/_templates/.gitkeep +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/_templates/autosummary/class.rst +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/changelog.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/conf.py +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/contributing.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/extensions/typed_returns.py +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/index.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/make.bat +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/references.bib +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/docs/references.md +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/data/hao1_annotations_small.zip +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/data/hao1_counts_small.zip +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/data/small_fino_bulks.zip +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/pp/__init__.py +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/src/rectanglepy/tl/__init__.py +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/TIL10_signature.txt +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/bulk_small.csv +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/cell_annotations_small.txt +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/quanTIseq_SimRNAseq_mixture_smaller.csv +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/sc_object_small.csv +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/signature_hao1.csv +0 -0
- {rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/test_tl.py +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Manual Upload to TestPyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
package:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v2
|
|
11
|
+
- name: Set up Python 3.10
|
|
12
|
+
uses: actions/setup-python@v2
|
|
13
|
+
with:
|
|
14
|
+
python-version: "3.10"
|
|
15
|
+
- name: Install build dependencies
|
|
16
|
+
run: python -m pip install --upgrade pip wheel twine build
|
|
17
|
+
- name: Build package
|
|
18
|
+
run: python -m build
|
|
19
|
+
- name: Check package
|
|
20
|
+
run: twine check --strict dist/*.whl
|
|
21
|
+
|
|
22
|
+
release:
|
|
23
|
+
name: Release
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout code
|
|
27
|
+
uses: actions/checkout@v3
|
|
28
|
+
|
|
29
|
+
- name: Set up Python 3.10
|
|
30
|
+
uses: actions/setup-python@v4
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.10"
|
|
33
|
+
|
|
34
|
+
- name: Install hatch
|
|
35
|
+
run: pip install hatch
|
|
36
|
+
|
|
37
|
+
- name: Install twine
|
|
38
|
+
run: pip install twine
|
|
39
|
+
|
|
40
|
+
- name: Build project for distribution
|
|
41
|
+
run: hatch build
|
|
42
|
+
|
|
43
|
+
- name: Publish a Python distribution to test PyPI
|
|
44
|
+
run: twine upload --repository testpypi dist/* -u __token__ -p ${{ secrets.TESTPYPI_API_TOKEN }}
|
|
@@ -10,6 +10,19 @@ and this project adheres to [Semantic Versioning][].
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.1.7] - 2024-07-25
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Fixed bug in the consensus method.
|
|
18
|
+
|
|
19
|
+
## [0.1.6] - 2024-05-07
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- Added consenus method to Rectangle
|
|
24
|
+
- RectangleSignatureResult now contains list of marker genes per cell type / cluster
|
|
25
|
+
|
|
13
26
|
## [0.1.0] - 2024-04-25
|
|
14
27
|
|
|
15
28
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rectanglepy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
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
|
|
@@ -31,6 +31,7 @@ License: MIT License
|
|
|
31
31
|
License-File: LICENSE
|
|
32
32
|
Requires-Python: >=3.10
|
|
33
33
|
Requires-Dist: loguru
|
|
34
|
+
Requires-Dist: numpy<2.0.0,>=1.0.0
|
|
34
35
|
Requires-Dist: pydeseq2==0.4.1
|
|
35
36
|
Requires-Dist: quadprog==0.1.11
|
|
36
37
|
Provides-Extra: dev
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
```
|
|
@@ -157,6 +157,11 @@
|
|
|
157
157
|
"collapsed": false
|
|
158
158
|
}
|
|
159
159
|
},
|
|
160
|
+
{
|
|
161
|
+
"metadata": {},
|
|
162
|
+
"cell_type": "markdown",
|
|
163
|
+
"source": "To deconvolute the bulk data in a single step, use the rectangle function. This function returns a tuple of the estimated cell type proportions and the signature result."
|
|
164
|
+
},
|
|
160
165
|
{
|
|
161
166
|
"cell_type": "code",
|
|
162
167
|
"outputs": [],
|
|
@@ -195,28 +200,21 @@
|
|
|
195
200
|
},
|
|
196
201
|
{
|
|
197
202
|
"cell_type": "markdown",
|
|
198
|
-
"source": [
|
|
199
|
-
"signature_result is a [`RectangleSignatureResult`](../generated/rectanglepy.pp.RectangleSignatureResult.rst) object. Results of estimations vary slightly from machine to machine (due to difference in theunderlying linear algebra packages)"
|
|
200
|
-
],
|
|
203
|
+
"source": "signature_result is a [`RectangleSignatureResult`](../generated/rectanglepy.pp.RectangleSignatureResult.rst) object. ",
|
|
201
204
|
"metadata": {
|
|
202
205
|
"collapsed": false
|
|
203
206
|
}
|
|
204
207
|
},
|
|
205
208
|
{
|
|
206
209
|
"cell_type": "markdown",
|
|
207
|
-
"source":
|
|
208
|
-
"## Even sampling and consensus"
|
|
209
|
-
],
|
|
210
|
+
"source": "## Running Rectangle in Consensus mode",
|
|
210
211
|
"metadata": {
|
|
211
212
|
"collapsed": false
|
|
212
213
|
}
|
|
213
214
|
},
|
|
214
215
|
{
|
|
215
216
|
"cell_type": "markdown",
|
|
216
|
-
"source":
|
|
217
|
-
"We recommend even subsampling of the sc data.\n",
|
|
218
|
-
"You can use the `sample_size` parameter to sample a fixed number of cells per cell type, and run the consensus multiple times to get a more robust result."
|
|
219
|
-
],
|
|
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.",
|
|
220
218
|
"metadata": {
|
|
221
219
|
"collapsed": false
|
|
222
220
|
}
|
|
@@ -224,14 +222,17 @@
|
|
|
224
222
|
{
|
|
225
223
|
"cell_type": "code",
|
|
226
224
|
"outputs": [],
|
|
227
|
-
"source":
|
|
228
|
-
"estimations, signature_result = rectangle.rectangle(sc_adata, bulks, consensus_runs=5, sample_size=1500)"
|
|
229
|
-
],
|
|
225
|
+
"source": "estimations, signature_result, consensus_result = rectangle.rectangle_consens(sc_adata, bulks, consensus_runs=5, sample_size=1500)",
|
|
230
226
|
"metadata": {
|
|
231
227
|
"collapsed": false
|
|
232
228
|
},
|
|
233
229
|
"execution_count": null
|
|
234
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
|
+
},
|
|
235
236
|
{
|
|
236
237
|
"cell_type": "markdown",
|
|
237
238
|
"source": [
|
|
@@ -4,7 +4,7 @@ requires = ["hatchling"]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rectanglepy"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.7"
|
|
8
8
|
description = "Hierarchical deconvolution of bulk transcriptomics"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -22,6 +22,7 @@ dependencies = [
|
|
|
22
22
|
"pydeseq2==0.4.1",
|
|
23
23
|
"quadprog==0.1.11",
|
|
24
24
|
"loguru",
|
|
25
|
+
"numpy>=1.0.0,<2.0.0",
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
[project.optional-dependencies]
|
|
@@ -0,0 +1,8 @@
|
|
|
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")
|
|
@@ -155,7 +155,7 @@ def _run_deseq2(countsig: pd.DataFrame, n_cpus: int = None) -> dict[str | int, p
|
|
|
155
155
|
|
|
156
156
|
def _de_analysis(
|
|
157
157
|
pseudo_count_sig, sc_data, annotations, p, lfc, optimize_cutoffs: bool, n_cpus: int = None, genes=None
|
|
158
|
-
) -> tuple[Series, dict[str,
|
|
158
|
+
) -> tuple[Series, dict[str, [str]] :, DataFrame | None]:
|
|
159
159
|
logger.info("Starting DE analysis")
|
|
160
160
|
deseq_results = _run_deseq2(pseudo_count_sig, n_cpus)
|
|
161
161
|
optimization_results = None
|
|
@@ -185,15 +185,15 @@ def _get_marker_genes(deseq_results, logfc, p, pseudo_count_sig):
|
|
|
185
185
|
optimal_condition_matrix = condition_number_matrices[optimal_condition_index]
|
|
186
186
|
|
|
187
187
|
markers = optimal_condition_matrix.index
|
|
188
|
-
marker_genes_per_cell_type =
|
|
188
|
+
marker_genes_per_cell_type = _get_marker_genes_per_cell_type(de_analysis_adjusted, optimal_condition_number)
|
|
189
189
|
return markers, marker_genes_per_cell_type
|
|
190
190
|
|
|
191
191
|
|
|
192
|
-
def
|
|
192
|
+
def _get_marker_genes_per_cell_type(de_analysis_adjusted, optimal_condition_number: int) -> dict[str, [str]]:
|
|
193
193
|
marker_genes_per_cell_type = {}
|
|
194
194
|
for annotation, result in de_analysis_adjusted.items():
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
number_of_genes = min(len(result), optimal_condition_number)
|
|
196
|
+
marker_genes_per_cell_type[annotation] = list(result.index[0:number_of_genes])
|
|
197
197
|
return marker_genes_per_cell_type
|
|
198
198
|
|
|
199
199
|
|
|
@@ -245,6 +245,7 @@ def build_rectangle_signatures(
|
|
|
245
245
|
subsample: bool = False,
|
|
246
246
|
sample_size: int = 1500,
|
|
247
247
|
n_cpus: int = None,
|
|
248
|
+
run: int = 0,
|
|
248
249
|
) -> RectangleSignatureResult:
|
|
249
250
|
r"""Builds rectangle signatures based on single-cell count data and annotations.
|
|
250
251
|
|
|
@@ -272,6 +273,8 @@ def build_rectangle_signatures(
|
|
|
272
273
|
The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
|
|
273
274
|
n_cpus
|
|
274
275
|
The number of cpus to use for the DE analysis. Defaults to the number of cpus available.
|
|
276
|
+
run
|
|
277
|
+
The consensus run number for the analysis. Defaults to 0.
|
|
275
278
|
|
|
276
279
|
Returns
|
|
277
280
|
-------
|
|
@@ -286,7 +289,7 @@ def build_rectangle_signatures(
|
|
|
286
289
|
|
|
287
290
|
annotations = adata.obs[cell_type_col]
|
|
288
291
|
if subsample:
|
|
289
|
-
annotations = _even(annotations, sample_size)
|
|
292
|
+
annotations = _even(annotations, sample_size, run)
|
|
290
293
|
adata = adata[annotations.index]
|
|
291
294
|
|
|
292
295
|
if layer is not None:
|
|
@@ -323,7 +326,9 @@ def build_rectangle_signatures(
|
|
|
323
326
|
)
|
|
324
327
|
|
|
325
328
|
clustered_biasfact = _create_bias_factors(clustered_signature, sc_counts, clustered_annotations)
|
|
326
|
-
clustered_genes
|
|
329
|
+
clustered_genes, clustered_marker_genes_per_cell_type, _ = _de_analysis(
|
|
330
|
+
clustered_signature, sc_counts, clustered_annotations, p, lfc, False
|
|
331
|
+
)
|
|
327
332
|
clustered_signature = _convert_to_cpm(clustered_signature)
|
|
328
333
|
return RectangleSignatureResult(
|
|
329
334
|
signature_genes=marker_genes,
|
|
@@ -335,6 +340,7 @@ def build_rectangle_signatures(
|
|
|
335
340
|
clustered_signature_genes=clustered_genes,
|
|
336
341
|
clustered_bias_factors=clustered_biasfact,
|
|
337
342
|
cluster_assignments=assignments,
|
|
343
|
+
marker_genes_per_cluster=clustered_marker_genes_per_cell_type,
|
|
338
344
|
)
|
|
339
345
|
|
|
340
346
|
|
|
@@ -445,7 +451,8 @@ def _reduce_to_common_genes(bulks: pd.DataFrame, sc_data: pd.DataFrame):
|
|
|
445
451
|
return bulks, sc_data
|
|
446
452
|
|
|
447
453
|
|
|
448
|
-
def _even(annotations: pd.Series, number: int) -> pd.Series:
|
|
454
|
+
def _even(annotations: pd.Series, number: int, run=0) -> pd.Series:
|
|
455
|
+
np.random.seed(run)
|
|
449
456
|
assert number > 0, "Number of cells must be greater than 0"
|
|
450
457
|
annotation_counts = annotations.value_counts()
|
|
451
458
|
selected_cells = []
|
|
@@ -29,16 +29,18 @@ class RectangleSignatureResult:
|
|
|
29
29
|
signature_genes: pd.Series,
|
|
30
30
|
bias_factors: pd.Series,
|
|
31
31
|
pseudobulk_sig_cpm: pd.DataFrame,
|
|
32
|
-
marker_genes_per_cell_type: dict[str,
|
|
32
|
+
marker_genes_per_cell_type: dict[str, [str]],
|
|
33
33
|
optimization_result: pd.DataFrame = None,
|
|
34
34
|
clustered_pseudobulk_sig_cpm: pd.DataFrame = None,
|
|
35
35
|
clustered_bias_factors: pd.Series = None,
|
|
36
|
+
marker_genes_per_cluster: dict[str, [str]] = None,
|
|
36
37
|
clustered_signature_genes: pd.Series = None,
|
|
37
38
|
cluster_assignments: list[int or str] = None,
|
|
38
39
|
):
|
|
39
40
|
self.signature_genes = signature_genes
|
|
40
41
|
self.bias_factors = bias_factors
|
|
41
42
|
self.pseudobulk_sig_cpm = pseudobulk_sig_cpm
|
|
43
|
+
self.marker_genes_per_cluster = marker_genes_per_cluster
|
|
42
44
|
self.marker_genes_per_cell_type = marker_genes_per_cell_type
|
|
43
45
|
self.optimization_result = optimization_result
|
|
44
46
|
self.clustered_pseudobulk_sig_cpm = clustered_pseudobulk_sig_cpm
|
|
@@ -46,21 +48,6 @@ class RectangleSignatureResult:
|
|
|
46
48
|
self.clustered_signature_genes = clustered_signature_genes
|
|
47
49
|
self.assignments = cluster_assignments
|
|
48
50
|
|
|
49
|
-
def cell_types_with_low_number_of_marker_genes(self) -> list[str]:
|
|
50
|
-
"""Returns the cell types with less than threshold marker genes.
|
|
51
|
-
|
|
52
|
-
Returns
|
|
53
|
-
-------
|
|
54
|
-
list[str]: The cell types with less than threshold marker genes.
|
|
55
|
-
|
|
56
|
-
"""
|
|
57
|
-
low_annotation_threshold = 30
|
|
58
|
-
return [
|
|
59
|
-
cell_type
|
|
60
|
-
for cell_type, count in self.marker_genes_per_cell_type.items()
|
|
61
|
-
if count < low_annotation_threshold
|
|
62
|
-
]
|
|
63
|
-
|
|
64
51
|
def get_signature_matrix(self, include_mrna_bias=True) -> pd.DataFrame:
|
|
65
52
|
"""Calculates the signature matrix by multiplying the pseudobulk_sig_cpm DataFrame subset by signature_genes and the bias_factors Series.
|
|
66
53
|
|
|
@@ -8,22 +8,38 @@ from .pp import RectangleSignatureResult, build_rectangle_signatures
|
|
|
8
8
|
from .tl import deconvolution
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
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(
|
|
12
28
|
adata: AnnData,
|
|
13
29
|
bulks: DataFrame,
|
|
14
30
|
cell_type_col: str = "cell_type",
|
|
15
31
|
*,
|
|
16
32
|
layer: str = None,
|
|
17
33
|
raw: bool = False,
|
|
18
|
-
subsample: bool =
|
|
34
|
+
subsample: bool = True,
|
|
19
35
|
sample_size: int = 1500,
|
|
20
|
-
consensus_runs: int =
|
|
36
|
+
consensus_runs: int = 5,
|
|
21
37
|
correct_mrna_bias: bool = True,
|
|
22
38
|
optimize_cutoffs=True,
|
|
23
39
|
p=0.015,
|
|
24
40
|
lfc=1.5,
|
|
25
41
|
n_cpus: int = None,
|
|
26
|
-
) -> tuple[DataFrame, RectangleSignatureResult]:
|
|
42
|
+
) -> tuple[DataFrame, RectangleSignatureResult, ConsensusResult]:
|
|
27
43
|
r"""All in one deconvolution method. Creates signatures and deconvolutes the bulk data. Has options for subsampling and consensus runs.
|
|
28
44
|
|
|
29
45
|
Parameters
|
|
@@ -39,26 +55,27 @@ def rectangle(
|
|
|
39
55
|
raw
|
|
40
56
|
A flag indicating whether to use the raw Anndata data. Defaults to False.
|
|
41
57
|
subsample : bool
|
|
42
|
-
A flag indicating whether to balance the single-cell data.
|
|
58
|
+
A flag indicating whether to balance the single-cell data.
|
|
43
59
|
sample_size : int
|
|
44
|
-
The number of cells to balance the single-cell data to.
|
|
60
|
+
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.
|
|
45
61
|
consensus_runs : int
|
|
46
|
-
The number of consensus runs to perform.
|
|
62
|
+
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.
|
|
47
63
|
optimize_cutoffs
|
|
48
|
-
Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
|
|
64
|
+
Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
|
|
49
65
|
p
|
|
50
66
|
The p-value threshold for the DE analysis (only used if optimize_cutoffs is False).
|
|
51
67
|
lfc
|
|
52
68
|
The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
|
|
53
69
|
n_cpus
|
|
54
|
-
The number of cpus to use for the DE analysis.
|
|
70
|
+
The number of cpus to use for the DE analysis. None value takes all cpus available.
|
|
55
71
|
correct_mrna_bias : bool
|
|
56
72
|
A flag indicating whether to correct for mRNA bias. Defaults to True.
|
|
57
73
|
|
|
58
74
|
Returns
|
|
59
75
|
-------
|
|
60
|
-
DataFrame : The estimated cell fractions.
|
|
61
|
-
RectangleSignatureResult : The result of the
|
|
76
|
+
DataFrame : The estimated cell fractions consens.
|
|
77
|
+
RectangleSignatureResult : The result of the last consensus run.
|
|
78
|
+
ConsensusResult : Estimations and rectangle signature results for each consensus run.
|
|
62
79
|
"""
|
|
63
80
|
assert isinstance(adata, AnnData), "adata must be an AnnData object"
|
|
64
81
|
assert isinstance(bulks, DataFrame), "bulks must be a DataFrame"
|
|
@@ -74,10 +91,11 @@ def rectangle(
|
|
|
74
91
|
subsample = True
|
|
75
92
|
|
|
76
93
|
estimations = []
|
|
94
|
+
rectangle_signature_results = []
|
|
77
95
|
most_recent_signatures = None
|
|
78
96
|
|
|
79
|
-
for
|
|
80
|
-
logger.info(f"Running consensus run {
|
|
97
|
+
for i in range(consensus_runs):
|
|
98
|
+
logger.info(f"Running consensus run {i + 1} of {consensus_runs}")
|
|
81
99
|
signatures = build_rectangle_signatures(
|
|
82
100
|
adata,
|
|
83
101
|
cell_type_col,
|
|
@@ -90,12 +108,76 @@ def rectangle(
|
|
|
90
108
|
n_cpus=n_cpus,
|
|
91
109
|
subsample=subsample,
|
|
92
110
|
sample_size=sample_size,
|
|
111
|
+
run=i,
|
|
93
112
|
)
|
|
113
|
+
rectangle_signature_results.append(signatures)
|
|
114
|
+
most_recent_signatures = signatures
|
|
94
115
|
cell_fractions = deconvolution(signatures, bulks, correct_mrna_bias, n_cpus)
|
|
95
116
|
estimations.append(cell_fractions)
|
|
96
|
-
most_recent_signatures = signatures
|
|
97
117
|
|
|
98
|
-
|
|
118
|
+
consensus_results = ConsensusResult(estimations, rectangle_signature_results)
|
|
119
|
+
return pd.concat(estimations).groupby(level=0).median(), most_recent_signatures, consensus_results
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def rectangle(
|
|
123
|
+
adata: AnnData,
|
|
124
|
+
bulks: DataFrame,
|
|
125
|
+
cell_type_col: str = "cell_type",
|
|
126
|
+
*,
|
|
127
|
+
layer: str = None,
|
|
128
|
+
raw: bool = False,
|
|
129
|
+
correct_mrna_bias: bool = True,
|
|
130
|
+
optimize_cutoffs=True,
|
|
131
|
+
p=0.015,
|
|
132
|
+
lfc=1.5,
|
|
133
|
+
n_cpus: int = None,
|
|
134
|
+
) -> tuple[DataFrame, RectangleSignatureResult]:
|
|
135
|
+
r"""All in one deconvolution method. Creates signatures and deconvolutes the bulk data. Has options for subsampling and consensus runs.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
adata
|
|
140
|
+
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.
|
|
141
|
+
bulks
|
|
142
|
+
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).
|
|
143
|
+
cell_type_col
|
|
144
|
+
The annotations corresponding to the single-cell count data. Series data should have the cell identifier as index and the annotations as values.
|
|
145
|
+
layer
|
|
146
|
+
The Anndata layer to use for the single-cell data.
|
|
147
|
+
raw
|
|
148
|
+
A flag indicating whether to use the raw Anndata data.
|
|
149
|
+
optimize_cutoffs
|
|
150
|
+
Indicates whether to optimize the p-value and log fold change cutoffs using gridsearch.
|
|
151
|
+
p
|
|
152
|
+
The p-value threshold for the DE analysis (only used if optimize_cutoffs is False).
|
|
153
|
+
lfc
|
|
154
|
+
The log fold change threshold for the DE analysis (only used if optimize_cutoffs is False).
|
|
155
|
+
n_cpus
|
|
156
|
+
The number of cpus to use for the DE analysis. None value takes all cpus available.
|
|
157
|
+
correct_mrna_bias : bool
|
|
158
|
+
A flag indicating whether to correct for mRNA bias. Defaults to True.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
DataFrame : The estimated cell fractions.
|
|
163
|
+
RectangleSignatureResult : The result of the rectangle signature analysis.
|
|
164
|
+
"""
|
|
165
|
+
estimations, signatures, _ = rectangle_consens(
|
|
166
|
+
adata,
|
|
167
|
+
bulks,
|
|
168
|
+
cell_type_col,
|
|
169
|
+
layer=layer,
|
|
170
|
+
raw=raw,
|
|
171
|
+
subsample=False,
|
|
172
|
+
sample_size=-1,
|
|
173
|
+
consensus_runs=1,
|
|
174
|
+
correct_mrna_bias=correct_mrna_bias,
|
|
175
|
+
optimize_cutoffs=optimize_cutoffs,
|
|
176
|
+
p=p,
|
|
177
|
+
lfc=lfc,
|
|
178
|
+
n_cpus=n_cpus,
|
|
179
|
+
)
|
|
180
|
+
return estimations, signatures
|
|
99
181
|
|
|
100
182
|
|
|
101
183
|
def load_tutorial_data() -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
|
|
@@ -257,7 +257,14 @@ def _deconvolute(signatures: RectangleSignatureResult, bulk: pd.Series, correct_
|
|
|
257
257
|
averaged_start_fractions = (start_fractions + union_direct_fraction) / 2
|
|
258
258
|
|
|
259
259
|
final_fractions = []
|
|
260
|
-
|
|
260
|
+
|
|
261
|
+
low_number_threshold = 30
|
|
262
|
+
cell_types_with_low_number_of_marker_genes = [
|
|
263
|
+
cell_type
|
|
264
|
+
for cell_type, num_marker_genes in signatures.marker_genes_per_cell_type.items()
|
|
265
|
+
if len(num_marker_genes) < low_number_threshold
|
|
266
|
+
]
|
|
267
|
+
|
|
261
268
|
for cell_type in list(averaged_start_fractions.index):
|
|
262
269
|
if cell_type in cell_types_with_low_number_of_marker_genes:
|
|
263
270
|
final_fractions.append(recursive_fractions[cell_type])
|
|
@@ -146,7 +146,7 @@ def test_build_rectangle_signatures(small_data):
|
|
|
146
146
|
adata = AnnData(sc_counts.T, obs=annotations.to_frame(name="cell_type"))
|
|
147
147
|
results = build_rectangle_signatures(adata, "cell_type", bulks=bulk.T, p=0.5, lfc=0.1, optimize_cutoffs=False)
|
|
148
148
|
assert results.assignments is None # not enough cells to cluster
|
|
149
|
-
assert 10 < len(results.signature_genes) <
|
|
149
|
+
assert 10 < len(results.signature_genes) < 400
|
|
150
150
|
|
|
151
151
|
|
|
152
152
|
def test_generate_pseudo_bulks(small_data):
|
|
@@ -2,6 +2,7 @@ import pandas as pd
|
|
|
2
2
|
from anndata import AnnData
|
|
3
3
|
|
|
4
4
|
import rectanglepy.rectangle
|
|
5
|
+
from rectanglepy import ConsensusResult
|
|
5
6
|
from rectanglepy.pp import RectangleSignatureResult
|
|
6
7
|
|
|
7
8
|
|
|
@@ -24,11 +25,21 @@ def test_rectangle():
|
|
|
24
25
|
|
|
25
26
|
def test_rectangle_consensus():
|
|
26
27
|
sc_data, annotations, bulks = rectanglepy.load_tutorial_data()
|
|
28
|
+
sc_data = sc_data.iloc[:, :500]
|
|
27
29
|
sc_data_adata = AnnData(sc_data, obs=annotations.to_frame(name="cell_type"))
|
|
28
30
|
|
|
29
|
-
result = rectanglepy.
|
|
30
|
-
sc_data_adata, bulks, optimize_cutoffs=False, p=0.5, lfc=0.0, consensus_runs=
|
|
31
|
+
result = rectanglepy.rectangle_consens(
|
|
32
|
+
sc_data_adata, bulks, optimize_cutoffs=False, p=0.5, lfc=0.0, consensus_runs=3, sample_size=50
|
|
31
33
|
)
|
|
32
34
|
|
|
33
35
|
assert isinstance(result[0], pd.DataFrame)
|
|
34
36
|
assert isinstance(result[1], RectangleSignatureResult)
|
|
37
|
+
assert isinstance(result[2], ConsensusResult)
|
|
38
|
+
|
|
39
|
+
# all bias factors should differ, else there is a problem with the random sampling
|
|
40
|
+
consensus_results = result[2]
|
|
41
|
+
signature_results = consensus_results.rectangle_signature_results
|
|
42
|
+
bias_factors = [result.bias_factors for result in signature_results]
|
|
43
|
+
assert bias_factors[0]["Monocytes"] != bias_factors[1]["Monocytes"]
|
|
44
|
+
assert bias_factors[0]["Monocytes"] != bias_factors[2]["Monocytes"]
|
|
45
|
+
assert bias_factors[1]["Monocytes"] != bias_factors[2]["Monocytes"]
|
rectanglepy-0.1.3/docs/api.md
DELETED
|
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
|
|
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
|
{rectanglepy-0.1.3 → rectanglepy-0.1.7}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|