seqpro 0.17.0__tar.gz → 0.18.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.
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/bench.yaml +1 -1
- {seqpro-0.17.0 → seqpro-0.18.0}/CHANGELOG.md +12 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/PKG-INFO +1 -1
- {seqpro-0.17.0 → seqpro-0.18.0}/pixi.lock +14 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/pixi.toml +4 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/pyproject.toml +1 -1
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_core.py +54 -1
- seqpro-0.18.0/tests/test_ragged_record_indexing.py +47 -0
- seqpro-0.18.0/tests/test_ragged_subclass.py +60 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.claude/skills/zensical/SKILL.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.gitattributes +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/bump.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/docs.yml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/lint.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/merge.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/publish.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/release-pipeline.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/release.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.github/workflows/test.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.gitignore +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/.pre-commit-config.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/CLAUDE.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/Cargo.lock +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/Cargo.toml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/LICENSE +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/README.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/benches/bench_tokenize_translate.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/benches/kshuffle.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/benchmarks/bench_ragged_backends.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/benchmarks/bench_to_packed.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/alphabets.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/bed.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/gtf.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/index.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/ragged.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/api/types.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/index.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/ragged.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/roadmap/rust-ragged.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-04-ragged-record-array.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-05-documentation-site.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-05-narwhals-coord-schema.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-05-ragged-zip-and-record-introspection.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-20-kshuffle-optimization.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-20-kshuffle-wilson-single-pass.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-20-release-pipeline.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-28-translate-lut-validation.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-31-flat-buffer-to-padded.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-31-rag-to-packed.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-05-translate-unknown-codon-policy.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-12-tokenize-lut-codspeed.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-18-rust-tokenize-translate.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-19-rust-ragged-core.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-20-rust-ragged-records.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-20-rust-ragged-spec-c.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-21-ragged-throughput-gate.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-21-rust-ragged-consumer-audit.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-04-ragged-record-array-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-05-documentation-site-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-05-narwhals-coord-schema-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-05-ragged-zip-and-record-introspection-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-kshuffle-optimization-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-kshuffle-wilson-single-pass-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-release-pipeline-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-28-translate-lut-and-validation-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-31-flat-buffer-to-padded-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-31-rag-to-packed-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-05-translate-unknown-codon-policy-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-12-tokenize-lut-codspeed-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-18-rust-tokenize-translate-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-19-rust-ragged-core-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-20-rust-ragged-nested-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-20-rust-ragged-records-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-21-ragged-throughput-gate-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-21-rust-ragged-audit-ledger.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-21-rust-ragged-consumer-audit-design.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/meta.yaml +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/__init__.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_analyzers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_cleaners.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_coords.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_encoders.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_modifiers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_numba.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_types.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/_utils.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/alphabets/__init__.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/alphabets/_alphabets.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/bed.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/experimental/_experimental.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/experimental/_visualizers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/gtf.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/py.typed +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/__init__.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_ak_interop.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_ingest.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_layout.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_ops.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_types.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/rag/_utils.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/transforms/__init__.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/transforms/augmentation.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/transforms/tmm.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/python/seqpro/xr/__init__.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/scratch_bench_rc.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/scratch_bench_to_padded.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/skills/seqpro/SKILL.md +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/kmer_encode.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/kshuffle.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/kshuffle_ref.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/lib.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/ragged.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/src/translate.rs +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/_shape_fixtures.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/bed/test_pyranges.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/bed/test_read.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/bed/test_sort.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/bed/test_with_length.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/bench_translate_lut.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/conftest.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_analyzers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_bench_tokenize.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_concatenate.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_coords.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_core_ragged_surface.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_encoders.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ingest.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_modifiers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ohe.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_rag_to_packed.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_core.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_core_records.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_nested_consumers.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_nested_diff.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_rc.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_ragged_to_padded.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_shape_matrix.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_tokenize.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_transforms.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_translate.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/tests/test_translate_rust.py +0 -0
- {seqpro-0.17.0 → seqpro-0.18.0}/zensical.toml +0 -0
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 0.18.0 (2026-06-23)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **rag**: reshape/squeeze/to_packed preserve Ragged subclass
|
|
6
|
+
- **rag**: __getitem__ preserves subclass on positional indexing
|
|
7
|
+
- **rag**: add _with_layout subclass-preserving constructor
|
|
8
|
+
|
|
9
|
+
### Fix
|
|
10
|
+
|
|
11
|
+
- **rag**: non-tuple record indexing matches numpy (A[x] == A[(x,)])
|
|
12
|
+
|
|
1
13
|
## 0.17.0 (2026-06-23)
|
|
2
14
|
|
|
3
15
|
### Feat
|
|
@@ -132,6 +132,7 @@ environments:
|
|
|
132
132
|
- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda
|
|
133
133
|
- conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda
|
|
134
134
|
- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda
|
|
135
|
+
- conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.1.2-pyh145f28c_0.conda
|
|
135
136
|
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda
|
|
136
137
|
- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhd8ed1ab_0.conda
|
|
137
138
|
- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda
|
|
@@ -262,6 +263,7 @@ environments:
|
|
|
262
263
|
- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.7-pyhcf101f3_0.conda
|
|
263
264
|
- conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda
|
|
264
265
|
- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda
|
|
266
|
+
- conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.1.2-pyh145f28c_0.conda
|
|
265
267
|
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda
|
|
266
268
|
- conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.6.0-pyhf9edf01_1.conda
|
|
267
269
|
- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda
|
|
@@ -6564,6 +6566,18 @@ packages:
|
|
|
6564
6566
|
- pkg:pypi/pickleshare?source=hash-mapping
|
|
6565
6567
|
size: 11748
|
|
6566
6568
|
timestamp: 1733327448200
|
|
6569
|
+
- conda: https://conda.anaconda.org/conda-forge/noarch/pip-26.1.2-pyh145f28c_0.conda
|
|
6570
|
+
sha256: 9e673d3c6003f416df11670a14b026a04e3a45ebec55357987e15b860f138f2a
|
|
6571
|
+
md5: 733cc07ed34162ac50b936464b163366
|
|
6572
|
+
depends:
|
|
6573
|
+
- python >=3.13.0a0
|
|
6574
|
+
license: MIT
|
|
6575
|
+
license_family: MIT
|
|
6576
|
+
purls:
|
|
6577
|
+
- pkg:pypi/pip?source=compressed-mapping
|
|
6578
|
+
run_exports: {}
|
|
6579
|
+
size: 1202377
|
|
6580
|
+
timestamp: 1780262809860
|
|
6567
6581
|
- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.3.8-pyhe01879c_0.conda
|
|
6568
6582
|
sha256: 0f48999a28019c329cd3f6fd2f01f09fc32cc832f7d6bbe38087ddac858feaa3
|
|
6569
6583
|
md5: 424844562f5d337077b445ec6b1398a7
|
|
@@ -95,6 +95,10 @@ bench = "pytest tests/test_bench_tokenize.py --codspeed"
|
|
|
95
95
|
rag-gate = "python benchmarks/bench_ragged_backends.py"
|
|
96
96
|
|
|
97
97
|
[feature.bench.dependencies]
|
|
98
|
+
# pip is required so `maturin develop` can install the editable build into
|
|
99
|
+
# the bench env. (`--uv` instead trips a uv installer bug on conda-managed
|
|
100
|
+
# transitive deps: "Installed distribution could not be found: ncls".)
|
|
101
|
+
pip = "*"
|
|
98
102
|
marimo = ">=0.23.5,<0.24"
|
|
99
103
|
seaborn = ">=0.13.2,<0.14"
|
|
100
104
|
statsmodels = ">=0.14.6,<0.15"
|
|
@@ -75,6 +75,15 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
75
75
|
validate_layout(data)
|
|
76
76
|
self._layout = data
|
|
77
77
|
|
|
78
|
+
def _with_layout(self, layout: Any) -> "Ragged[Any]":
|
|
79
|
+
"""Reconstruct a same-kind container around ``layout``, preserving the
|
|
80
|
+
concrete subclass. Bypasses ``__init__`` (subclasses carry no state beyond
|
|
81
|
+
``_layout``; see the subclassing contract). Used by structural transforms
|
|
82
|
+
so a ``Ragged`` subclass survives slicing/reshape/squeeze/to_packed."""
|
|
83
|
+
obj = object.__new__(type(self))
|
|
84
|
+
obj._layout = layout
|
|
85
|
+
return obj
|
|
86
|
+
|
|
78
87
|
@property
|
|
79
88
|
def _is_record(self) -> bool:
|
|
80
89
|
return isinstance(self._layout, RecordLayout)
|
|
@@ -425,6 +434,19 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
425
434
|
def __getitem__(
|
|
426
435
|
self, where: Any
|
|
427
436
|
) -> "NDArray[Any] | bytes | dict[str, Any] | Ragged[Any]":
|
|
437
|
+
result = self._getitem(where)
|
|
438
|
+
# Preserve the concrete subclass for positional (structural) results.
|
|
439
|
+
# A string key is field extraction -> keep the bare field as base Ragged.
|
|
440
|
+
# Non-Ragged results (dict / bytes / ndarray / scalar) pass through.
|
|
441
|
+
if (
|
|
442
|
+
type(self) is not Ragged
|
|
443
|
+
and not isinstance(where, str)
|
|
444
|
+
and isinstance(result, Ragged)
|
|
445
|
+
):
|
|
446
|
+
return self._with_layout(result._layout)
|
|
447
|
+
return result
|
|
448
|
+
|
|
449
|
+
def _getitem(self, where: Any) -> Any:
|
|
428
450
|
# np.newaxis / None: insert a size-1 leading axis.
|
|
429
451
|
# e.g. shape (batch, None)[None] -> (1, batch, None)
|
|
430
452
|
if where is None:
|
|
@@ -813,7 +835,18 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
813
835
|
except KeyError:
|
|
814
836
|
raise KeyError(where)
|
|
815
837
|
return Ragged(field) # field.offsets[0] is the shared object (zero-copy)
|
|
816
|
-
|
|
838
|
+
# numpy contract: a non-tuple key is treated as a 1-tuple (A[x] == A[(x,)]).
|
|
839
|
+
# For a single-ragged-axis record with >1 leading fixed axis, route through
|
|
840
|
+
# the multidim peel path directly (under the SAME guard it requires, so we
|
|
841
|
+
# never re-dispatch through __getitem__ and risk recursion). Records that are
|
|
842
|
+
# not single-None fall through to the flat record-rows path unchanged.
|
|
843
|
+
if (
|
|
844
|
+
not isinstance(where, tuple)
|
|
845
|
+
and self.rag_dim > 1
|
|
846
|
+
and rec.shape.count(None) == 1
|
|
847
|
+
):
|
|
848
|
+
return self._getitem_tuple_multidim((where,))
|
|
849
|
+
return self._getitem_record_rows(where)
|
|
817
850
|
|
|
818
851
|
def _gather_indices(
|
|
819
852
|
self, where: Any, starts: "NDArray[Any]", stops: "NDArray[Any]"
|
|
@@ -1161,6 +1194,14 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
1161
1194
|
|
|
1162
1195
|
def squeeze(
|
|
1163
1196
|
self, axis: int | tuple[int, ...] | None = None
|
|
1197
|
+
) -> "Ragged[Any] | NDArray[Any]":
|
|
1198
|
+
result = self._squeeze_impl(axis)
|
|
1199
|
+
if type(self) is not Ragged and isinstance(result, Ragged):
|
|
1200
|
+
return self._with_layout(result._layout)
|
|
1201
|
+
return result
|
|
1202
|
+
|
|
1203
|
+
def _squeeze_impl(
|
|
1204
|
+
self, axis: int | tuple[int, ...] | None = None
|
|
1164
1205
|
) -> "Ragged[Any] | NDArray[Any]":
|
|
1165
1206
|
if isinstance(self._layout, RecordLayout):
|
|
1166
1207
|
return Ragged.from_fields(
|
|
@@ -1210,6 +1251,12 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
1210
1251
|
)
|
|
1211
1252
|
|
|
1212
1253
|
def reshape(self, *shape: int | None) -> "Ragged[Any]":
|
|
1254
|
+
result = self._reshape_impl(*shape)
|
|
1255
|
+
if type(self) is not Ragged and isinstance(result, Ragged):
|
|
1256
|
+
return self._with_layout(result._layout)
|
|
1257
|
+
return result
|
|
1258
|
+
|
|
1259
|
+
def _reshape_impl(self, *shape: int | None) -> "Ragged[Any]":
|
|
1213
1260
|
if isinstance(self._layout, RecordLayout):
|
|
1214
1261
|
return Ragged.from_fields(
|
|
1215
1262
|
{f: Ragged(fl).reshape(*shape) for f, fl in self._layout.fields.items()}
|
|
@@ -1270,6 +1317,12 @@ class Ragged(NDArrayOperatorsMixin, Generic[RDTYPE_co]):
|
|
|
1270
1317
|
return raw.reshape(reshape_arg)
|
|
1271
1318
|
|
|
1272
1319
|
def to_packed(self, *, copy: bool = True) -> "Ragged[Any]":
|
|
1320
|
+
result = self._to_packed_impl(copy=copy)
|
|
1321
|
+
if type(self) is not Ragged and isinstance(result, Ragged):
|
|
1322
|
+
return self._with_layout(result._layout)
|
|
1323
|
+
return result
|
|
1324
|
+
|
|
1325
|
+
def _to_packed_impl(self, *, copy: bool = True) -> "Ragged[Any]":
|
|
1273
1326
|
from ._ops import _pack_parts
|
|
1274
1327
|
|
|
1275
1328
|
if isinstance(self._layout, RecordLayout):
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from seqpro.rag import Ragged
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _multidim_record():
|
|
8
|
+
"""A (3, 2, None) numeric record: 6 ragged segments over a (batch=3, ploidy=2)
|
|
9
|
+
leading grid."""
|
|
10
|
+
lengths = np.array([[1, 2], [3, 1], [2, 2]], np.uint32) # (3, 2)
|
|
11
|
+
data = np.arange(int(lengths.sum()), dtype=np.int32)
|
|
12
|
+
start = Ragged.from_lengths(data, lengths.reshape(-1)).reshape(3, 2, None)
|
|
13
|
+
return Ragged.from_fields({"start": start})
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.parametrize(
|
|
17
|
+
"key",
|
|
18
|
+
[
|
|
19
|
+
0,
|
|
20
|
+
slice(1, 3),
|
|
21
|
+
slice(None),
|
|
22
|
+
np.array([True, False, True]),
|
|
23
|
+
np.array([0, 2]),
|
|
24
|
+
],
|
|
25
|
+
ids=["int", "slice", "full_slice", "mask", "int_array"],
|
|
26
|
+
)
|
|
27
|
+
def test_nontuple_equals_one_tuple_multidim_record(key):
|
|
28
|
+
"""numpy contract: rec[k] must equal rec[(k,)] for a multi-leading-axis record."""
|
|
29
|
+
rec = _multidim_record()
|
|
30
|
+
got = rec[key]
|
|
31
|
+
want = rec[(key,)]
|
|
32
|
+
assert type(got) is type(want), (type(got), type(want))
|
|
33
|
+
if isinstance(want, Ragged):
|
|
34
|
+
assert got.shape == want.shape, (got.shape, want.shape)
|
|
35
|
+
np.testing.assert_array_equal(
|
|
36
|
+
np.asarray(got["start"].data), np.asarray(want["start"].data)
|
|
37
|
+
)
|
|
38
|
+
np.testing.assert_array_equal(
|
|
39
|
+
np.asarray(got["start"].offsets[0]), np.asarray(want["start"].offsets[0])
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_slice_preserves_ploidy_axis():
|
|
44
|
+
"""Regression for the specific bug: rec[1:3] kept the ploidy axis."""
|
|
45
|
+
rec = _multidim_record()
|
|
46
|
+
assert rec[1:3].shape == (2, 2, None)
|
|
47
|
+
assert rec[0].shape == (2, None)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from seqpro.rag import Ragged
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class _Sub(Ragged):
|
|
7
|
+
__slots__ = ()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _ragged():
|
|
11
|
+
return Ragged.from_lengths(
|
|
12
|
+
np.arange(6, dtype=np.int32), np.array([2, 1, 3], np.uint32)
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_with_layout_preserves_subclass():
|
|
17
|
+
sub = _Sub(_ragged()._layout)
|
|
18
|
+
out = sub._with_layout(_ragged()._layout)
|
|
19
|
+
assert type(out) is _Sub
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_with_layout_base_returns_base():
|
|
23
|
+
base = _ragged()
|
|
24
|
+
out = base._with_layout(_ragged()._layout)
|
|
25
|
+
assert type(out) is Ragged
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _record():
|
|
29
|
+
a = Ragged.from_lengths(
|
|
30
|
+
np.arange(6, dtype=np.int32), np.array([2, 1, 3], np.uint32)
|
|
31
|
+
)
|
|
32
|
+
b = Ragged.from_lengths(
|
|
33
|
+
np.arange(6, dtype=np.int32) * 10, np.array([2, 1, 3], np.uint32)
|
|
34
|
+
)
|
|
35
|
+
return Ragged.from_fields({"a": a, "b": b})
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_getitem_positional_preserves_subclass():
|
|
39
|
+
sub = _Sub(_record()._layout)
|
|
40
|
+
assert type(sub[0:2]) is _Sub # positional row slice -> subclass
|
|
41
|
+
assert type(sub[np.array([0, 2])]) is _Sub
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_getitem_field_extraction_stays_base():
|
|
45
|
+
sub = _Sub(_record()._layout)
|
|
46
|
+
assert type(sub["a"]) is Ragged # string key -> bare field, base Ragged
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_reshape_squeeze_to_packed_preserve_subclass():
|
|
50
|
+
sub = _Sub(_record()._layout) # shape (3, None) record
|
|
51
|
+
assert type(sub.reshape(1, 3, None)) is _Sub
|
|
52
|
+
assert type(sub.reshape(1, 3, None).squeeze(0)) is _Sub
|
|
53
|
+
assert type(sub.to_packed()) is _Sub
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_reshape_squeeze_to_packed_base_unchanged():
|
|
57
|
+
base = _record()
|
|
58
|
+
assert type(base.reshape(1, 3, None)) is Ragged
|
|
59
|
+
assert type(base.reshape(1, 3, None).squeeze(0)) is Ragged
|
|
60
|
+
assert type(base.to_packed()) is Ragged
|
|
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
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-20-kshuffle-wilson-single-pass.md
RENAMED
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-05-28-translate-lut-validation.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-05-translate-unknown-codon-policy.md
RENAMED
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-18-rust-tokenize-translate.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/plans/2026-06-21-rust-ragged-consumer-audit.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-04-ragged-record-array-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-05-documentation-site-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-05-narwhals-coord-schema-design.md
RENAMED
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-kshuffle-optimization-design.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-20-release-pipeline-design.md
RENAMED
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-05-31-flat-buffer-to-padded-design.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-12-tokenize-lut-codspeed-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-18-rust-tokenize-translate-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-19-rust-ragged-core-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-20-rust-ragged-nested-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-20-rust-ragged-records-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-21-ragged-throughput-gate-design.md
RENAMED
|
File without changes
|
{seqpro-0.17.0 → seqpro-0.18.0}/docs/superpowers/specs/2026-06-21-rust-ragged-audit-ledger.md
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
|
|
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
|
|
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
|