seqpro 0.13.0__tar.gz → 0.14.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.13.0 → seqpro-0.14.0}/.github/workflows/release.yaml +2 -9
- {seqpro-0.13.0 → seqpro-0.14.0}/CHANGELOG.md +22 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/PKG-INFO +1 -1
- seqpro-0.14.0/benchmarks/bench_to_packed.py +187 -0
- seqpro-0.14.0/docs/superpowers/plans/2026-05-31-rag-to-packed.md +815 -0
- seqpro-0.14.0/docs/superpowers/specs/2026-05-31-rag-to-packed-design.md +134 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/pyproject.toml +1 -1
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_encoders.py +4 -5
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/alphabets/_alphabets.py +1 -2
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/__init__.py +2 -1
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/_array.py +22 -11
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/_ops.py +148 -5
- {seqpro-0.13.0 → seqpro-0.14.0}/skills/seqpro/SKILL.md +3 -2
- seqpro-0.14.0/tests/test_rag_to_packed.py +130 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.claude/skills/zensical-setup/.skillfish.json +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.claude/skills/zensical-setup/SKILL.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.gitattributes +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/bump.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/docs.yml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/lint.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/merge.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/publish.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/release-pipeline.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.github/workflows/test.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.gitignore +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/.pre-commit-config.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/CLAUDE.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/Cargo.lock +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/Cargo.toml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/LICENSE +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/README.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/benches/kshuffle.rs +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/alphabets.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/bed.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/gtf.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/index.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/ragged.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/api/types.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/index.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/ragged.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-04-ragged-record-array.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-05-documentation-site.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-05-narwhals-coord-schema.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-05-ragged-zip-and-record-introspection.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-20-kshuffle-optimization.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-20-kshuffle-wilson-single-pass.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-20-release-pipeline.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-28-translate-lut-validation.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/plans/2026-05-31-flat-buffer-to-padded.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-04-ragged-record-array-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-05-documentation-site-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-05-narwhals-coord-schema-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-05-ragged-zip-and-record-introspection-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-20-kshuffle-optimization-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-20-kshuffle-wilson-single-pass-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-20-release-pipeline-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-28-translate-lut-and-validation-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/docs/superpowers/specs/2026-05-31-flat-buffer-to-padded-design.md +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/meta.yaml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/pixi.lock +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/pixi.toml +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/__init__.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_analyzers.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_cleaners.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_coords.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_modifiers.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_numba.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_types.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/_utils.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/alphabets/__init__.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/bed.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/experimental/_experimental.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/experimental/_visualizers.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/gtf.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/py.typed +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/_gufuncs.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/_types.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/rag/_utils.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/transforms/__init__.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/transforms/augmentation.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/transforms/tmm.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/python/seqpro/xr/__init__.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/scratch_bench_rc.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/scratch_bench_to_padded.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/src/kmer_encode.rs +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/src/kshuffle.rs +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/src/kshuffle_ref.rs +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/src/lib.rs +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/_shape_fixtures.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/bed/test_pyranges.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/bed/test_read.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/bed/test_sort.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/bed/test_with_length.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/bench_translate_lut.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/conftest.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_analyzers.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_coords.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_encoders.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_modifiers.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_ohe.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_ragged.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_ragged_rc.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_ragged_to_padded.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_shape_matrix.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_tokenize.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_transforms.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/tests/test_translate.py +0 -0
- {seqpro-0.13.0 → seqpro-0.14.0}/zensical.toml +0 -0
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
name: Create release
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- '[0-9]+.[0-9]+.[0-9]+'
|
|
7
4
|
workflow_dispatch:
|
|
8
5
|
inputs:
|
|
9
6
|
tag:
|
|
@@ -30,15 +27,11 @@ jobs:
|
|
|
30
27
|
- uses: actions/checkout@v4
|
|
31
28
|
with:
|
|
32
29
|
fetch-depth: 0
|
|
30
|
+
ref: ${{ inputs.tag }}
|
|
33
31
|
|
|
34
32
|
- name: Resolve tag
|
|
35
33
|
id: tag
|
|
36
|
-
run:
|
|
37
|
-
case "${{ github.event_name }}" in
|
|
38
|
-
push) echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT ;;
|
|
39
|
-
workflow_dispatch) echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT ;;
|
|
40
|
-
workflow_call) echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT ;;
|
|
41
|
-
esac
|
|
34
|
+
run: echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT
|
|
42
35
|
|
|
43
36
|
- name: Extract changelog section
|
|
44
37
|
run: |
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.14.0 (2026-06-01)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **rag**: add Ragged.to_packed method and export to_packed
|
|
6
|
+
- **rag**: add Numba-parallelized to_packed for flat layouts
|
|
7
|
+
|
|
8
|
+
### Fix
|
|
9
|
+
|
|
10
|
+
- **ci**: check out release tag and drop duplicate release trigger
|
|
11
|
+
- **rag**: produce canonical list-of-records layout in to_packed
|
|
12
|
+
|
|
13
|
+
### Refactor
|
|
14
|
+
|
|
15
|
+
- **rag**: make Ragged.to_packed copy keyword-only; add multibyte-trailing test
|
|
16
|
+
- **rag**: drop unused as_contiguous packing path in unbox
|
|
17
|
+
|
|
18
|
+
### Perf
|
|
19
|
+
|
|
20
|
+
- **rag**: microbenchmark to_packed throughput vs ak.to_packed
|
|
21
|
+
- **rag**: use to_packed at internal ak.to_packed call sites
|
|
22
|
+
|
|
1
23
|
## 0.13.0 (2026-06-01)
|
|
2
24
|
|
|
3
25
|
### Feat
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""Microbenchmark: seqpro.rag.to_packed vs ak.to_packed vs NumPy gather.
|
|
2
|
+
|
|
3
|
+
Run in the bench env:
|
|
4
|
+
pixi run -e bench python benchmarks/bench_to_packed.py --out bench_to_packed
|
|
5
|
+
|
|
6
|
+
Outputs <out>.csv and <out>_*.png. Sweeps n_rows, mean length, length
|
|
7
|
+
distribution, source (RAM vs memmap), dtype itemsize, and thread count, and
|
|
8
|
+
prints an effect-size ranking of which axes most affect the speedup ratio.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import os
|
|
15
|
+
import time
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def make_lengths(rng, n_rows, mean_len, distribution):
|
|
22
|
+
if distribution == "uniform":
|
|
23
|
+
lo, hi = max(1, mean_len // 2), mean_len * 2
|
|
24
|
+
return rng.integers(lo, hi + 1, size=n_rows)
|
|
25
|
+
# long-tailed: most rows short, a few very long (load imbalance)
|
|
26
|
+
lengths = rng.integers(1, max(2, mean_len // 4), size=n_rows)
|
|
27
|
+
n_big = max(1, n_rows // 100)
|
|
28
|
+
lengths[rng.choice(n_rows, n_big, replace=False)] = mean_len * 50
|
|
29
|
+
return lengths
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build(rng, n_rows, mean_len, distribution, dtype, source, tmpdir):
|
|
33
|
+
import seqpro.rag as spr
|
|
34
|
+
|
|
35
|
+
lengths = make_lengths(rng, n_rows, mean_len, distribution).astype(np.int64)
|
|
36
|
+
total = int(lengths.sum())
|
|
37
|
+
if source == "memmap":
|
|
38
|
+
path = Path(tmpdir) / "data.dat"
|
|
39
|
+
data = np.memmap(path, dtype=dtype, mode="w+", shape=(total,))
|
|
40
|
+
data[:] = rng.integers(0, 255, size=total).astype(dtype)
|
|
41
|
+
else:
|
|
42
|
+
data = rng.integers(0, 255, size=total).astype(dtype)
|
|
43
|
+
rag = spr.Ragged.from_lengths(data, lengths)
|
|
44
|
+
# reorder so the layout is an (unpacked) ListArray, forcing a real gather
|
|
45
|
+
return rag[rng.permutation(n_rows)], total * np.dtype(dtype).itemsize
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def numpy_gather(rag):
|
|
49
|
+
import seqpro.rag as spr
|
|
50
|
+
|
|
51
|
+
parts = rag._parts
|
|
52
|
+
offs = parts.offsets
|
|
53
|
+
starts, stops = (offs[0], offs[1]) if offs.ndim == 2 else (offs[:-1], offs[1:])
|
|
54
|
+
lengths = stops - starts
|
|
55
|
+
out_off = np.empty(lengths.size + 1, dtype=np.int64)
|
|
56
|
+
out_off[0] = 0
|
|
57
|
+
np.cumsum(lengths, out=out_off[1:])
|
|
58
|
+
idx = np.repeat(starts - out_off[:-1], lengths) + np.arange(int(out_off[-1]))
|
|
59
|
+
return spr.Ragged.from_offsets(parts.data[idx], parts.shape, out_off)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def timeit(fn, arg, repeats):
|
|
63
|
+
fn(arg) # warm up (JIT, caches)
|
|
64
|
+
times = []
|
|
65
|
+
for _ in range(repeats):
|
|
66
|
+
t0 = time.perf_counter()
|
|
67
|
+
fn(arg)
|
|
68
|
+
times.append(time.perf_counter() - t0)
|
|
69
|
+
return float(np.median(times))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
p = argparse.ArgumentParser()
|
|
74
|
+
p.add_argument("--out", default="bench_to_packed")
|
|
75
|
+
p.add_argument("--repeats", type=int, default=5)
|
|
76
|
+
p.add_argument(
|
|
77
|
+
"--n-rows", type=int, nargs="+", default=[1000, 10000, 100000, 1000000]
|
|
78
|
+
)
|
|
79
|
+
p.add_argument("--mean-len", type=int, nargs="+", default=[16, 256, 4096])
|
|
80
|
+
p.add_argument("--distributions", nargs="+", default=["uniform", "longtail"])
|
|
81
|
+
p.add_argument("--sources", nargs="+", default=["ram", "memmap"])
|
|
82
|
+
p.add_argument("--dtypes", nargs="+", default=["uint8", "float64"])
|
|
83
|
+
p.add_argument("--threads", type=int, nargs="+", default=[int(os.cpu_count() or 1)])
|
|
84
|
+
args = p.parse_args()
|
|
85
|
+
|
|
86
|
+
import awkward as ak
|
|
87
|
+
import pandas as pd
|
|
88
|
+
import seqpro.rag as spr # noqa: F401 (ensures kernel import)
|
|
89
|
+
import tempfile
|
|
90
|
+
|
|
91
|
+
rng = np.random.default_rng(0)
|
|
92
|
+
rows = []
|
|
93
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
94
|
+
for nthreads in args.threads:
|
|
95
|
+
import numba
|
|
96
|
+
|
|
97
|
+
numba.set_num_threads(nthreads)
|
|
98
|
+
impls = {
|
|
99
|
+
"seqpro": lambda r: r.to_packed(),
|
|
100
|
+
"ak": lambda r: spr.Ragged(ak.to_packed(r)),
|
|
101
|
+
"numpy": numpy_gather,
|
|
102
|
+
}
|
|
103
|
+
for n_rows in args.n_rows:
|
|
104
|
+
for mean_len in args.mean_len:
|
|
105
|
+
for dist in args.distributions:
|
|
106
|
+
for src in args.sources:
|
|
107
|
+
for dt in args.dtypes:
|
|
108
|
+
rag, nbytes = build(
|
|
109
|
+
rng, n_rows, mean_len, dist, dt, src, tmp
|
|
110
|
+
)
|
|
111
|
+
for name, fn in impls.items():
|
|
112
|
+
t = timeit(fn, rag, args.repeats)
|
|
113
|
+
rows.append(
|
|
114
|
+
dict(
|
|
115
|
+
impl=name,
|
|
116
|
+
n_rows=n_rows,
|
|
117
|
+
mean_len=mean_len,
|
|
118
|
+
distribution=dist,
|
|
119
|
+
source=src,
|
|
120
|
+
dtype=dt,
|
|
121
|
+
threads=nthreads,
|
|
122
|
+
seconds=t,
|
|
123
|
+
gbps=nbytes / t / 1e9,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
df = pd.DataFrame(rows)
|
|
128
|
+
df.to_csv(f"{args.out}.csv", index=False)
|
|
129
|
+
_plots_and_summary(df, args.out)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _plots_and_summary(df, out):
|
|
133
|
+
import matplotlib
|
|
134
|
+
|
|
135
|
+
matplotlib.use("Agg")
|
|
136
|
+
import matplotlib.pyplot as plt
|
|
137
|
+
import seaborn as sns
|
|
138
|
+
|
|
139
|
+
# throughput vs n_rows, faceted by mean_len x dtype, hue impl
|
|
140
|
+
g = sns.relplot(
|
|
141
|
+
data=df,
|
|
142
|
+
x="n_rows",
|
|
143
|
+
y="gbps",
|
|
144
|
+
hue="impl",
|
|
145
|
+
style="source",
|
|
146
|
+
col="mean_len",
|
|
147
|
+
row="dtype",
|
|
148
|
+
kind="line",
|
|
149
|
+
marker="o",
|
|
150
|
+
facet_kws=dict(sharey=False),
|
|
151
|
+
)
|
|
152
|
+
g.set(xscale="log")
|
|
153
|
+
g.savefig(f"{out}_throughput.png", dpi=120)
|
|
154
|
+
|
|
155
|
+
# thread scaling for seqpro
|
|
156
|
+
if df["threads"].nunique() > 1:
|
|
157
|
+
sub = df[df.impl == "seqpro"]
|
|
158
|
+
gt = sns.relplot(
|
|
159
|
+
data=sub, x="threads", y="gbps", hue="mean_len", kind="line", marker="o"
|
|
160
|
+
)
|
|
161
|
+
gt.savefig(f"{out}_threads.png", dpi=120)
|
|
162
|
+
plt.close("all")
|
|
163
|
+
|
|
164
|
+
# effect-size ranking on speedup (seqpro / ak) — goal 2
|
|
165
|
+
wide = df.pivot_table(
|
|
166
|
+
index=["n_rows", "mean_len", "distribution", "source", "dtype", "threads"],
|
|
167
|
+
columns="impl",
|
|
168
|
+
values="gbps",
|
|
169
|
+
).reset_index()
|
|
170
|
+
wide["speedup"] = wide["seqpro"] / wide["ak"]
|
|
171
|
+
print("\n=== Speedup (seqpro / ak) summary ===")
|
|
172
|
+
print(wide["speedup"].describe())
|
|
173
|
+
print("\n=== Mean speedup by axis (effect size) ===")
|
|
174
|
+
axes = ["n_rows", "mean_len", "distribution", "source", "dtype", "threads"]
|
|
175
|
+
spreads = {}
|
|
176
|
+
for ax in axes:
|
|
177
|
+
means = wide.groupby(ax)["speedup"].mean()
|
|
178
|
+
spreads[ax] = means.max() - means.min()
|
|
179
|
+
print(f"\n{ax}:")
|
|
180
|
+
print(means)
|
|
181
|
+
print("\n=== Axes ranked by speedup spread (most influential first) ===")
|
|
182
|
+
for ax, s in sorted(spreads.items(), key=lambda kv: -kv[1]):
|
|
183
|
+
print(f" {ax:14s} spread={s:.2f}")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
main()
|