rectanglepy 1.2.1__tar.gz → 1.3.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-1.2.1 → rectanglepy-1.3.0}/.bumpversion.cfg +1 -1
  2. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/PKG-INFO +1 -2
  3. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/pyproject.toml +1 -2
  4. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/rectangle.py +7 -4
  5. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/tl/deconvolution.py +12 -4
  6. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.cruft.json +0 -0
  7. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.editorconfig +0 -0
  8. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  9. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  10. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  11. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  12. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/workflows/build.yaml +0 -0
  13. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/workflows/release.yaml +0 -0
  14. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/workflows/release_testpypi.yaml +0 -0
  15. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.github/workflows/test.yaml +0 -0
  16. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.gitignore +0 -0
  17. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.pre-commit-config.yaml +0 -0
  18. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/.readthedocs.yaml +0 -0
  19. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/CHANGELOG.md +0 -0
  20. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/LICENSE +0 -0
  21. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/README.md +0 -0
  22. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/Makefile +0 -0
  23. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/_static/.gitkeep +0 -0
  24. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/_static/rec_logo.001.png +0 -0
  25. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/_templates/.gitkeep +0 -0
  26. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/_templates/autosummary/class.rst +0 -0
  27. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/api.md +0 -0
  28. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/changelog.md +0 -0
  29. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/conf.py +0 -0
  30. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/contributing.md +0 -0
  31. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/extensions/typed_returns.py +0 -0
  32. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/index.md +0 -0
  33. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/installation.md +0 -0
  34. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/make.bat +0 -0
  35. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/notebooks/example.ipynb +0 -0
  36. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/references.bib +0 -0
  37. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/references.md +0 -0
  38. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/docs/tutorials.md +0 -0
  39. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/__init__.py +0 -0
  40. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/data/hao1_annotations_small.zip +0 -0
  41. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/data/hao1_counts_small.zip +0 -0
  42. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/data/small_fino_bulks.zip +0 -0
  43. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/pp/__init__.py +0 -0
  44. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/pp/create_signature.py +0 -0
  45. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/pp/rectangle_signature.py +0 -0
  46. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/src/rectanglepy/tl/__init__.py +0 -0
  47. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/TIL10_signature.txt +0 -0
  48. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/bulk_small.csv +0 -0
  49. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/cell_annotations_small.txt +0 -0
  50. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/quanTIseq_SimRNAseq_mixture_smaller.csv +0 -0
  51. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/quanTIseq_SimRNAseq_read_fractions_small.txt +0 -0
  52. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/sc_object_small.csv +0 -0
  53. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/data/signature_hao1.csv +0 -0
  54. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/test_pp.py +0 -0
  55. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/test_rectangle.py +0 -0
  56. {rectanglepy-1.2.1 → rectanglepy-1.3.0}/tests/test_tl.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 1.2.1
2
+ current_version = 1.3.0
3
3
  tag = True
4
4
  commit = True
5
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rectanglepy
3
- Version: 1.2.1
3
+ Version: 1.3.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
@@ -690,7 +690,6 @@ Requires-Dist: osqp>=1.0.5
690
690
  Requires-Dist: pandas<3.0.0,>=2.0.0
691
691
  Requires-Dist: pydeseq2==0.4.11
692
692
  Requires-Dist: scipy==1.13.0
693
- Requires-Dist: setuptools>=80.0.0
694
693
  Requires-Dist: statsmodels>=0.14.1
695
694
  Provides-Extra: dev
696
695
  Requires-Dist: bump2version; extra == 'dev'
@@ -4,7 +4,7 @@ requires = ["hatchling"]
4
4
 
5
5
  [project]
6
6
  name = "rectanglepy"
7
- version = "1.2.1"
7
+ version = "1.3.0"
8
8
  description = "Hierarchical deconvolution of bulk transcriptomics"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -27,7 +27,6 @@ dependencies = [
27
27
  "numpy>=1.0.0,<2.0.0",
28
28
  "anndata>=0.8.0,<0.10.9",
29
29
  "statsmodels>=0.14.1",
30
- "setuptools>=80.0.0",
31
30
 
32
31
  ]
33
32
 
@@ -1,8 +1,9 @@
1
+ from importlib.resources import files
2
+
1
3
  import pandas as pd
2
4
  from anndata import AnnData
3
5
  from loguru import logger
4
6
  from pandas import DataFrame
5
- from pkg_resources import resource_stream
6
7
 
7
8
  from .pp import RectangleSignatureResult, build_rectangle_signatures
8
9
  from .tl import deconvolution
@@ -93,13 +94,15 @@ def load_tutorial_data() -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
93
94
  -------
94
95
  The single-cell count data, annotations, and bulk data.
95
96
  """
96
- with resource_stream(__name__, "data/hao1_annotations_small.zip") as annotations_file:
97
+ data_dir = files(__package__) / "data"
98
+
99
+ with (data_dir / "hao1_annotations_small.zip").open("rb") as annotations_file:
97
100
  annotations = pd.read_csv(annotations_file, index_col=0, compression="zip")["0"]
98
101
 
99
- with resource_stream(__name__, "data/hao1_counts_small.zip") as counts_file:
102
+ with (data_dir / "hao1_counts_small.zip").open("rb") as counts_file:
100
103
  sc_counts = pd.read_csv(counts_file, index_col=0, compression="zip").astype("int")
101
104
 
102
- with resource_stream(__name__, "data/small_fino_bulks.zip") as bulks_file:
105
+ with (data_dir / "small_fino_bulks.zip").open("rb") as bulks_file:
103
106
  bulks = pd.read_csv(bulks_file, index_col=0, compression="zip")
104
107
 
105
108
  return sc_counts.T, annotations, bulks.T
@@ -121,13 +121,18 @@ def solve_qp(
121
121
  P = P / scale
122
122
  q = q / scale
123
123
 
124
+ # OSQP can return noticeably different solutions from active-set QP when P is singular/ill-conditioned.
125
+ # Add tiny ridge to make the problem strictly convex and closer to quadprog behavior.
126
+ ridge = 1e-8
127
+ P = ((P + P.T) / 2.0) + ridge * np.eye(n_vars, dtype=np.float64)
128
+
124
129
  # OSQP uses l <= A x <= u
125
130
  A = C.T # (n_constraints, n_vars)
126
131
  l = b
127
132
  u = np.full_like(l, np.inf, dtype=np.float64)
128
133
 
129
134
  # Sparse matrices (required/expected)
130
- P_sp = sp.csc_matrix((P + P.T) / 2.0) # enforce symmetry
135
+ P_sp = sp.csc_matrix(P)
131
136
  A_sp = sp.csc_matrix(A)
132
137
 
133
138
  solver = osqp.OSQP()
@@ -138,9 +143,12 @@ def solve_qp(
138
143
  l=l,
139
144
  u=u,
140
145
  verbose=False,
141
- eps_abs=1e-5,
142
- eps_rel=1e-5,
143
- max_iter=10000,
146
+ eps_abs=1e-8,
147
+ eps_rel=1e-8,
148
+ max_iter=50000,
149
+ polish=True,
150
+ warm_start=False,
151
+ scaled_termination=False,
144
152
  )
145
153
 
146
154
  res = solver.solve()
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