scatrans 0.9.8.dev5__tar.gz → 0.9.8.dev6__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.
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/CHANGELOG.md +6 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/PKG-INFO +1 -1
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/_version.py +2 -2
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_regression_bugs.py +9 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/.github/workflows/ci.yml +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/.github/workflows/publish.yml +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/.gitignore +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/.pre-commit-config.yaml +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/CITATION.cff +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/LICENSE +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/MANIFEST.in +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/README.md +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/conftest.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/conftest_fixtures.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/examples/memento_de_example.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/examples/real_data_template.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/examples/synthetic_active_transcription.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/pyproject.toml +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/scatrans.egg-info/SOURCES.txt +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/setup.cfg +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/__init__.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/_de.py +12 -12
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/_permutation.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/_utils.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/_velocity.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/DATA_LICENSES.md +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Hs_GO_Biological_Process_2026.txt +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Hs_KEGG_2026.txt +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Mm_GO_Biological_Process_2026.txt +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Mm_KEGG_2026.txt +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Mus_musculus.GRCm39.115_gene_features.parquet +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/README.md +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/human_GRCh38_2024A_gene_features.parquet +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/mouse_2020A_gene_features.parquet +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/enrich.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/generate_gene_features.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/pl.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/pp_bias.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/qc.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/tl.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/__init__.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/conftest.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_basic.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_de_backends.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_de_edge_cases.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_enrich_api.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_enrich_go.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_pl_coverage.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_pl_extended.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_pp_bias_cli.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_public_api.py +0 -0
- {scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/tests/test_tl_coverage.py +0 -0
|
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
## [0.9.8 bugfix 2026-07-04]
|
|
9
9
|
|
|
10
10
|
### Fixed
|
|
11
|
+
- **CI pytest failure on matrix legs without `pydeseq2`**: two new pseudobulk regression tests
|
|
12
|
+
(`test_strict_pydeseq2_counts_rejects_log_normalized_*`) now use the same
|
|
13
|
+
`@pytest.mark.skipif(importlib.util.find_spec("pydeseq2") is None, ...)` guard as
|
|
14
|
+
`tests/test_de_backends.py`, instead of relying on production-code check ordering.
|
|
15
|
+
Restored PyDESeq2 `ImportError` (missing dependency) ahead of data-validation `ValueError`
|
|
16
|
+
in `_run_de_wrapper`, so users without `pydeseq2` see the install hint first.
|
|
11
17
|
- **Pseudobulk `strict_pydeseq2_counts` check ran on already-rounded data**: `_pseudobulk_with_layers`
|
|
12
18
|
always rounds aggregated sums to integers, so the PyDESeq2 count-likeness check in
|
|
13
19
|
`_run_de_wrapper` (which inspected the rounded pseudobulk `.X`) could never detect that the
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.9.8.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 9, 8, '
|
|
21
|
+
__version__ = version = '0.9.8.dev6'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 9, 8, 'dev6')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import importlib.util
|
|
5
6
|
import logging
|
|
6
7
|
import sys
|
|
7
8
|
from unittest.mock import patch
|
|
@@ -194,6 +195,10 @@ def test_diagnose_design_kb_python_layers(adata_mature_nascent):
|
|
|
194
195
|
assert 0.0 <= diag["unspliced_global_fraction"] <= 1.0
|
|
195
196
|
|
|
196
197
|
|
|
198
|
+
@pytest.mark.skipif(
|
|
199
|
+
importlib.util.find_spec("pydeseq2") is None,
|
|
200
|
+
reason="pydeseq2 not installed",
|
|
201
|
+
)
|
|
197
202
|
def test_strict_pydeseq2_counts_rejects_log_normalized_pseudobulk():
|
|
198
203
|
"""Rounding before integer check must not let log-normalized pb data through."""
|
|
199
204
|
rng = np.random.default_rng(7)
|
|
@@ -238,6 +243,10 @@ def test_pseudobulk_with_layers_flags_non_count_source_before_rounding():
|
|
|
238
243
|
assert pb.uns["pb_x_is_count_like"] is False
|
|
239
244
|
|
|
240
245
|
|
|
246
|
+
@pytest.mark.skipif(
|
|
247
|
+
importlib.util.find_spec("pydeseq2") is None,
|
|
248
|
+
reason="pydeseq2 not installed",
|
|
249
|
+
)
|
|
241
250
|
def test_strict_pydeseq2_counts_rejects_log_normalized_layer_end_to_end():
|
|
242
251
|
"""End-to-end: use_pseudobulk=True + pb_x_layer pointing at log-normalized data must raise,
|
|
243
252
|
not silently round the log-normalized sums into look-alike integers."""
|
|
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
|
|
@@ -185,6 +185,18 @@ def _run_de_wrapper(
|
|
|
185
185
|
_ann_log.setLevel(_prev_ann)
|
|
186
186
|
|
|
187
187
|
if is_pseudobulk and pb_backend == "pydeseq2":
|
|
188
|
+
try:
|
|
189
|
+
from pydeseq2.dds import DeseqDataSet
|
|
190
|
+
from pydeseq2.ds import DeseqStats
|
|
191
|
+
except ImportError as e:
|
|
192
|
+
raise ImportError(
|
|
193
|
+
"PyDESeq2 backend requested but 'pydeseq2' is not installed.\n"
|
|
194
|
+
"Install with:\n"
|
|
195
|
+
' pip install "scatrans[pseudobulk]"\n'
|
|
196
|
+
"or\n"
|
|
197
|
+
" pip install pydeseq2"
|
|
198
|
+
) from e
|
|
199
|
+
|
|
188
200
|
n_t = (ad_temp.obs[use_groupby] == target_group).sum()
|
|
189
201
|
n_r = (ad_temp.obs[use_groupby] == reference_group).sum()
|
|
190
202
|
if n_t < 2 or n_r < 2:
|
|
@@ -256,18 +268,6 @@ def _run_de_wrapper(
|
|
|
256
268
|
f"No genes passed the DESeq2 count filter (sum(counts) >= {min_counts_per_gene})."
|
|
257
269
|
)
|
|
258
270
|
|
|
259
|
-
try:
|
|
260
|
-
from pydeseq2.dds import DeseqDataSet
|
|
261
|
-
from pydeseq2.ds import DeseqStats
|
|
262
|
-
except ImportError as e:
|
|
263
|
-
raise ImportError(
|
|
264
|
-
"PyDESeq2 backend requested but 'pydeseq2' is not installed.\n"
|
|
265
|
-
"Install with:\n"
|
|
266
|
-
' pip install "scatrans[pseudobulk]"\n'
|
|
267
|
-
"or\n"
|
|
268
|
-
" pip install pydeseq2"
|
|
269
|
-
) from e
|
|
270
|
-
|
|
271
271
|
condition = ad_temp.obs[use_groupby].astype(str).values
|
|
272
272
|
metadata = pd.DataFrame(
|
|
273
273
|
{use_groupby: pd.Categorical(condition, categories=[reference_group, target_group])},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Hs_GO_Biological_Process_2026.txt
RENAMED
|
File without changes
|
|
File without changes
|
{scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/Mm_GO_Biological_Process_2026.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scatrans-0.9.8.dev5 → scatrans-0.9.8.dev6}/src/scatrans/data/mouse_2020A_gene_features.parquet
RENAMED
|
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
|