rectanglepy 0.1.7__tar.gz → 0.1.8__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.7 → rectanglepy-0.1.8}/.bumpversion.cfg +1 -1
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/CHANGELOG.md +10 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/PKG-INFO +2 -1
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/pyproject.toml +2 -1
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/pp/create_signature.py +11 -4
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/pp/rectangle_signature.py +4 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/rectangle.py +15 -3
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/test_rectangle.py +9 -3
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.cruft.json +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.editorconfig +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/workflows/build.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/workflows/release.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/workflows/release_testpypi.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.github/workflows/test.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.gitignore +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.pre-commit-config.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/.readthedocs.yaml +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/LICENSE +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/README.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/Makefile +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/_static/.gitkeep +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/_templates/.gitkeep +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/_templates/autosummary/class.rst +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/api.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/changelog.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/conf.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/contributing.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/extensions/typed_returns.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/index.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/make.bat +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/notebooks/example.ipynb +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/references.bib +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/docs/references.md +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/__init__.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/data/hao1_annotations_small.zip +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/data/hao1_counts_small.zip +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/data/small_fino_bulks.zip +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/pp/__init__.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/tl/__init__.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/src/rectanglepy/tl/deconvolution.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/TIL10_signature.txt +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/bulk_small.csv +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/cell_annotations_small.txt +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/quanTIseq_SimRNAseq_mixture_smaller.csv +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/sc_object_small.csv +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/signature_hao1.csv +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/test_pp.py +0 -0
- {rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/test_tl.py +0 -0
|
@@ -10,6 +10,16 @@ and this project adheres to [Semantic Versioning][].
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.1.8] - 2024-09-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- RectangleSignatureResult now returns correlation of bulk genes with the calculated Unknown cell type fraction
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- The consensus method now returns the estimations normalized to 1
|
|
22
|
+
|
|
13
23
|
## [0.1.7] - 2024-07-25
|
|
14
24
|
|
|
15
25
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rectanglepy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
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
|
|
@@ -30,6 +30,7 @@ License: MIT License
|
|
|
30
30
|
SOFTWARE.
|
|
31
31
|
License-File: LICENSE
|
|
32
32
|
Requires-Python: >=3.10
|
|
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.1
|
|
@@ -4,7 +4,7 @@ requires = ["hatchling"]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rectanglepy"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.8"
|
|
8
8
|
description = "Hierarchical deconvolution of bulk transcriptomics"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -23,6 +23,7 @@ dependencies = [
|
|
|
23
23
|
"quadprog==0.1.11",
|
|
24
24
|
"loguru",
|
|
25
25
|
"numpy>=1.0.0,<2.0.0",
|
|
26
|
+
"anndata>=0.8.0,<0.10.9",
|
|
26
27
|
]
|
|
27
28
|
|
|
28
29
|
[project.optional-dependencies]
|
|
@@ -34,7 +34,9 @@ def _create_condition_number_matrices(de_adjusted, pseudo_signature):
|
|
|
34
34
|
loop_range = min(longest_de_analysis, 200)
|
|
35
35
|
range_minimum = 30
|
|
36
36
|
|
|
37
|
-
if loop_range <
|
|
37
|
+
if loop_range < 8:
|
|
38
|
+
range_minimum = 2
|
|
39
|
+
elif loop_range < range_minimum:
|
|
38
40
|
range_minimum = 8
|
|
39
41
|
|
|
40
42
|
for i in range(range_minimum, loop_range):
|
|
@@ -368,9 +370,14 @@ def _optimize_parameters(
|
|
|
368
370
|
bulks, real_fractions = _generate_pseudo_bulks(sc_data, annotations, genes)
|
|
369
371
|
for p in ps:
|
|
370
372
|
for lfc in lfcs:
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
try:
|
|
374
|
+
rmse, pearson_r = _assess_parameter_fit(
|
|
375
|
+
lfc, p, bulks, real_fractions, pseudo_signature_counts, de_results
|
|
376
|
+
)
|
|
377
|
+
logger.info(f"RMSE:{rmse}, Pearson R:{pearson_r} for p={p}, lfc={lfc}")
|
|
378
|
+
results.append({"p": p, "lfc": lfc, "rmse": rmse, "pearson_r": pearson_r})
|
|
379
|
+
except Exception as e:
|
|
380
|
+
logger.error(f"Error in assessing parameter fit for p={p}, lfc={lfc}: {e}")
|
|
374
381
|
|
|
375
382
|
results_df = pd.DataFrame(results)
|
|
376
383
|
results_df = results_df.sort_values(by=["pearson_r", "rmse"], ascending=[False, True])
|
|
@@ -22,6 +22,8 @@ class RectangleSignatureResult:
|
|
|
22
22
|
The number of marker genes per cell type, as a dictionary. Keys are cell type names, values are the number of marker genes.
|
|
23
23
|
optimization_result
|
|
24
24
|
The result of the p lfc cut off optimization, as a pd.DataFrame. Contains the following columns: p, lfc, pearson_r, rsme
|
|
25
|
+
unkn_gene_corr
|
|
26
|
+
The correlation between the unknown cell type and the genes linked to the unknown cell type.
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
def __init__(
|
|
@@ -36,6 +38,7 @@ class RectangleSignatureResult:
|
|
|
36
38
|
marker_genes_per_cluster: dict[str, [str]] = None,
|
|
37
39
|
clustered_signature_genes: pd.Series = None,
|
|
38
40
|
cluster_assignments: list[int or str] = None,
|
|
41
|
+
unkn_gene_corr: pd.Series = None,
|
|
39
42
|
):
|
|
40
43
|
self.signature_genes = signature_genes
|
|
41
44
|
self.bias_factors = bias_factors
|
|
@@ -47,6 +50,7 @@ class RectangleSignatureResult:
|
|
|
47
50
|
self.clustered_bias_factors = clustered_bias_factors
|
|
48
51
|
self.clustered_signature_genes = clustered_signature_genes
|
|
49
52
|
self.assignments = cluster_assignments
|
|
53
|
+
self.unkn_gene_corr = unkn_gene_corr
|
|
50
54
|
|
|
51
55
|
def get_signature_matrix(self, include_mrna_bias=True) -> pd.DataFrame:
|
|
52
56
|
"""Calculates the signature matrix by multiplying the pseudobulk_sig_cpm DataFrame subset by signature_genes and the bias_factors Series.
|
|
@@ -110,13 +110,17 @@ def rectangle_consens(
|
|
|
110
110
|
sample_size=sample_size,
|
|
111
111
|
run=i,
|
|
112
112
|
)
|
|
113
|
-
rectangle_signature_results.append(signatures)
|
|
114
113
|
most_recent_signatures = signatures
|
|
115
114
|
cell_fractions = deconvolution(signatures, bulks, correct_mrna_bias, n_cpus)
|
|
116
115
|
estimations.append(cell_fractions)
|
|
117
|
-
|
|
116
|
+
unkn_gene_corr = _genes_linked_to_unkn(bulks, cell_fractions["Unknown"])
|
|
117
|
+
signatures.unkn_gene_corr = unkn_gene_corr
|
|
118
|
+
rectangle_signature_results.append(signatures)
|
|
119
|
+
consensus_estimations = pd.concat(estimations).groupby(level=0).median()
|
|
120
|
+
# normalize the estimations to 1
|
|
121
|
+
consensus_estimations = consensus_estimations.div(consensus_estimations.sum(axis=1), axis=0)
|
|
118
122
|
consensus_results = ConsensusResult(estimations, rectangle_signature_results)
|
|
119
|
-
return
|
|
123
|
+
return consensus_estimations, most_recent_signatures, consensus_results
|
|
120
124
|
|
|
121
125
|
|
|
122
126
|
def rectangle(
|
|
@@ -197,3 +201,11 @@ def load_tutorial_data() -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
|
|
|
197
201
|
bulks = pd.read_csv(bulks_file, index_col=0, compression="zip")
|
|
198
202
|
|
|
199
203
|
return sc_counts.T, annotations, bulks.T
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _genes_linked_to_unkn(bulks: DataFrame, unkn_fractions: pd.Series):
|
|
207
|
+
genes = bulks.columns
|
|
208
|
+
corr = []
|
|
209
|
+
for gene in genes:
|
|
210
|
+
corr.append(unkn_fractions.corr(bulks.loc[:, gene]))
|
|
211
|
+
return pd.Series(corr, index=genes).sort_values(ascending=False)
|
|
@@ -15,12 +15,15 @@ def test_load_tutorial_data():
|
|
|
15
15
|
|
|
16
16
|
def test_rectangle():
|
|
17
17
|
sc_data, annotations, bulks = rectanglepy.load_tutorial_data()
|
|
18
|
+
sc_data = sc_data.iloc[:, :500]
|
|
18
19
|
sc_data_adata = AnnData(sc_data, obs=annotations.to_frame(name="cell_type"))
|
|
19
20
|
|
|
20
21
|
result = rectanglepy.rectangle(sc_data_adata, bulks)
|
|
22
|
+
estimations, signatures = result
|
|
21
23
|
|
|
22
|
-
assert isinstance(
|
|
23
|
-
assert isinstance(
|
|
24
|
+
assert isinstance(estimations, pd.DataFrame)
|
|
25
|
+
assert isinstance(signatures, RectangleSignatureResult)
|
|
26
|
+
assert isinstance(signatures.unkn_gene_corr, pd.Series)
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
def test_rectangle_consensus():
|
|
@@ -36,10 +39,13 @@ def test_rectangle_consensus():
|
|
|
36
39
|
assert isinstance(result[1], RectangleSignatureResult)
|
|
37
40
|
assert isinstance(result[2], ConsensusResult)
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
estimations = result[0]
|
|
40
43
|
consensus_results = result[2]
|
|
41
44
|
signature_results = consensus_results.rectangle_signature_results
|
|
42
45
|
bias_factors = [result.bias_factors for result in signature_results]
|
|
46
|
+
# there was a problem with the random sampling, the bias factors should differ
|
|
43
47
|
assert bias_factors[0]["Monocytes"] != bias_factors[1]["Monocytes"]
|
|
44
48
|
assert bias_factors[0]["Monocytes"] != bias_factors[2]["Monocytes"]
|
|
45
49
|
assert bias_factors[1]["Monocytes"] != bias_factors[2]["Monocytes"]
|
|
50
|
+
# in the consensus we have to make sure that the estimations are again normalized to 1
|
|
51
|
+
assert estimations.sum(axis=1).all() == 1.0
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rectanglepy-0.1.7 → rectanglepy-0.1.8}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|