gp3sequencespy 0.1.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.
- gp3sequencespy-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +38 -0
- gp3sequencespy-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- gp3sequencespy-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +32 -0
- gp3sequencespy-0.1.0/.github/pull_request_template.md +17 -0
- gp3sequencespy-0.1.0/.github/workflows/ci.yml +83 -0
- gp3sequencespy-0.1.0/.github/workflows/docs.yml +41 -0
- gp3sequencespy-0.1.0/.github/workflows/release-check.yml +57 -0
- gp3sequencespy-0.1.0/.gitignore +30 -0
- gp3sequencespy-0.1.0/CHANGELOG.md +81 -0
- gp3sequencespy-0.1.0/CITATION.cff +20 -0
- gp3sequencespy-0.1.0/CODE_OF_CONDUCT.md +25 -0
- gp3sequencespy-0.1.0/CONTRIBUTING.md +38 -0
- gp3sequencespy-0.1.0/LICENSE +21 -0
- gp3sequencespy-0.1.0/PARITY_EXCEPTIONS.md +67 -0
- gp3sequencespy-0.1.0/PARITY_TEST_MATRIX.md +181 -0
- gp3sequencespy-0.1.0/PKG-INFO +103 -0
- gp3sequencespy-0.1.0/README.md +48 -0
- gp3sequencespy-0.1.0/RELEASE_CHECKLIST.md +41 -0
- gp3sequencespy-0.1.0/REPRODUCIBILITY.md +98 -0
- gp3sequencespy-0.1.0/SECURITY.md +25 -0
- gp3sequencespy-0.1.0/SIGNATURE_PARITY.md +40 -0
- gp3sequencespy-0.1.0/docs/articles/choosing-a-sequence-analysis-method.md +132 -0
- gp3sequencespy-0.1.0/docs/articles/consensus-and-group-comparisons.md +52 -0
- gp3sequencespy-0.1.0/docs/articles/contiguous-motif-workflow.md +118 -0
- gp3sequencespy-0.1.0/docs/articles/distances-clustering-and-stability.md +75 -0
- gp3sequencespy-0.1.0/docs/articles/extended-sequence-visualisations.md +60 -0
- gp3sequencespy-0.1.0/docs/articles/getting-started-with-gp3sequences.md +160 -0
- gp3sequencespy-0.1.0/docs/articles/index.md +23 -0
- gp3sequencespy-0.1.0/docs/articles/latent-models-and-optional-adapters.md +67 -0
- gp3sequencespy-0.1.0/docs/articles/longitudinal-panel-sequences.md +69 -0
- gp3sequencespy-0.1.0/docs/articles/multichannel-and-covariate-hmms.md +59 -0
- gp3sequencespy-0.1.0/docs/articles/noncontiguous-subsequence-mining.md +64 -0
- gp3sequencespy-0.1.0/docs/articles/reproducible-sequence-analysis-case-study.md +128 -0
- gp3sequencespy-0.1.0/docs/articles/sequence-data-validation-and-preparation.md +113 -0
- gp3sequencespy-0.1.0/docs/articles/sequence-inference-and-randomization.md +62 -0
- gp3sequencespy-0.1.0/docs/articles/time-varying-condition-models.md +68 -0
- gp3sequencespy-0.1.0/docs/articles/transition-networks-and-higher-order-models.md +48 -0
- gp3sequencespy-0.1.0/docs/index.md +29 -0
- gp3sequencespy-0.1.0/docs/parity.md +12 -0
- gp3sequencespy-0.1.0/docs/reference/api.md +571 -0
- gp3sequencespy-0.1.0/docs/reference/index.md +6 -0
- gp3sequencespy-0.1.0/docs/release-readiness.md +28 -0
- gp3sequencespy-0.1.0/docs/stylesheets/extra.css +2 -0
- gp3sequencespy-0.1.0/mkdocs.yml +65 -0
- gp3sequencespy-0.1.0/parity/README.md +13 -0
- gp3sequencespy-0.1.0/parity/__init__.py +1 -0
- gp3sequencespy-0.1.0/parity/actual/.gitkeep +0 -0
- gp3sequencespy-0.1.0/parity/canonicalizers/__init__.py +1 -0
- gp3sequencespy-0.1.0/parity/canonicalizers/csv_contracts.py +54 -0
- gp3sequencespy-0.1.0/parity/compare_oracle.py +47 -0
- gp3sequencespy-0.1.0/parity/expected/README.md +15 -0
- gp3sequencespy-0.1.0/parity/fixtures/minimal.csv +17 -0
- gp3sequencespy-0.1.0/parity/generate_python_outputs.py +70 -0
- gp3sequencespy-0.1.0/parity/r_scripts/generate_reference_outputs.R +82 -0
- gp3sequencespy-0.1.0/parity/signature_audit.py +456 -0
- gp3sequencespy-0.1.0/pyproject.toml +74 -0
- gp3sequencespy-0.1.0/reference/R_REFERENCE.md +18 -0
- gp3sequencespy-0.1.0/reference/api_manifest.json +488 -0
- gp3sequencespy-0.1.0/reference/article_manifest.json +77 -0
- gp3sequencespy-0.1.0/reference/oracle_validation.json +71 -0
- gp3sequencespy-0.1.0/reference/release_candidate_contract_0.1.0.json +17 -0
- gp3sequencespy-0.1.0/reference/signature_parity_matrix.json +3564 -0
- gp3sequencespy-0.1.0/reference/signatures.json +83 -0
- gp3sequencespy-0.1.0/reference/source_manifest.json +117 -0
- gp3sequencespy-0.1.0/reference/test_manifest.json +112 -0
- gp3sequencespy-0.1.0/reference/test_parity_matrix.json +912 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/__init__.py +220 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/_advanced.py +441 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/_exceptions.py +14 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/_types.py +189 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/adapters.py +256 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/analysis_audit.py +462 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/capabilities.py +102 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/consensus.py +394 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/covariate_hmm.py +576 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/data.py +979 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/distances.py +878 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/hmm.py +644 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/inference.py +342 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/motif_visualisation.py +550 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/motifs.py +517 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/multichannel_hmm.py +425 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/networks.py +514 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/panel.py +282 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/py.typed +0 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/subsequences.py +347 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/summaries.py +441 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/time_models.py +450 -0
- gp3sequencespy-0.1.0/src/gp3sequencespy/visualisations.py +420 -0
- gp3sequencespy-0.1.0/tests/test_core_port.py +492 -0
- gp3sequencespy-0.1.0/tests/test_docs_contract.py +48 -0
- gp3sequencespy-0.1.0/tests/test_numpy_pandas_compat.py +19 -0
- gp3sequencespy-0.1.0/tests/test_parity_harness.py +57 -0
- gp3sequencespy-0.1.0/tests/test_public_api.py +79 -0
- gp3sequencespy-0.1.0/tests/test_r_advanced_deterministic_contracts.py +473 -0
- gp3sequencespy-0.1.0/tests/test_r_block_completion.py +296 -0
- gp3sequencespy-0.1.0/tests/test_r_deterministic_contracts.py +680 -0
- gp3sequencespy-0.1.0/tests/test_r_hclust_oracle_regressions.py +128 -0
- gp3sequencespy-0.1.0/tests/test_r_remaining_contracts.py +620 -0
- gp3sequencespy-0.1.0/tests/test_release_contract.py +73 -0
- gp3sequencespy-0.1.0/tests/test_remaining_r_api.py +184 -0
- gp3sequencespy-0.1.0/tests/test_signature_parity.py +108 -0
- gp3sequencespy-0.1.0/tests/test_time_mssm_backend.py +131 -0
- gp3sequencespy-0.1.0/uv.lock +2872 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a reproducible defect or parity regression
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: Thanks for reporting a reproducible problem.
|
|
9
|
+
- type: input
|
|
10
|
+
id: version
|
|
11
|
+
attributes:
|
|
12
|
+
label: gp3sequencespy version or commit
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: reproduce
|
|
17
|
+
attributes:
|
|
18
|
+
label: Minimal reproducible example
|
|
19
|
+
render: python
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: expected
|
|
24
|
+
attributes:
|
|
25
|
+
label: Expected behavior
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: observed
|
|
30
|
+
attributes:
|
|
31
|
+
label: Observed behavior
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: environment
|
|
36
|
+
attributes:
|
|
37
|
+
label: Environment
|
|
38
|
+
description: OS, Python, pandas/numpy/scipy versions, and optional extras.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a parity-preserving or Python-native extension
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: problem
|
|
8
|
+
attributes:
|
|
9
|
+
label: Scientific or software problem
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed API or behavior
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: dropdown
|
|
19
|
+
id: relationship
|
|
20
|
+
attributes:
|
|
21
|
+
label: Relationship to frozen R 0.3.0
|
|
22
|
+
options:
|
|
23
|
+
- Direct parity counterpart
|
|
24
|
+
- Parity clarification or bug fix
|
|
25
|
+
- Python-native extension after frozen parity
|
|
26
|
+
- Unsure
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: evidence
|
|
31
|
+
attributes:
|
|
32
|
+
label: Methodological references or examples
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Describe the change and the scientific/software contract it affects.
|
|
4
|
+
|
|
5
|
+
## Parity impact
|
|
6
|
+
|
|
7
|
+
- [ ] No frozen R contract is changed.
|
|
8
|
+
- [ ] Frozen parity behavior is intentionally changed/clarified and tests were updated.
|
|
9
|
+
- [ ] `PARITY_EXCEPTIONS.md` was updated if an R → Python translation is involved.
|
|
10
|
+
|
|
11
|
+
## Validation
|
|
12
|
+
|
|
13
|
+
- [ ] Ruff lint and format checks pass.
|
|
14
|
+
- [ ] mypy passes.
|
|
15
|
+
- [ ] Full pytest suite passes.
|
|
16
|
+
- [ ] Documentation builds with `mkdocs build --strict` when applicable.
|
|
17
|
+
- [ ] Built-artifact behavior was checked when packaging metadata changed.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
quality:
|
|
14
|
+
name: Static quality / Python 3.11
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: astral-sh/setup-uv@v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
enable-cache: true
|
|
22
|
+
- name: Sync environment
|
|
23
|
+
run: uv sync --extra dev --extra time
|
|
24
|
+
- name: Ruff lint
|
|
25
|
+
run: uv run ruff check src tests parity
|
|
26
|
+
- name: Ruff format
|
|
27
|
+
run: uv run ruff format --check src tests parity
|
|
28
|
+
- name: mypy
|
|
29
|
+
run: uv run mypy src/gp3sequencespy
|
|
30
|
+
- name: Frozen API contract
|
|
31
|
+
run: >-
|
|
32
|
+
uv run python -c "import json,pathlib,gp3sequencespy as g;
|
|
33
|
+
names=[x['name'] for x in json.loads(pathlib.Path('reference/api_manifest.json').read_text())];
|
|
34
|
+
missing=[x for x in names if not hasattr(g,x)];
|
|
35
|
+
hidden=[x for x in names if x not in g.__all__];
|
|
36
|
+
print('reference:',len(names),'present:',len(names)-len(missing),'missing:',missing,'not_in___all__:',hidden);
|
|
37
|
+
assert len(names)==81 and not missing and not hidden"
|
|
38
|
+
- name: Frozen R block ledger
|
|
39
|
+
run: >-
|
|
40
|
+
uv run python -c "import json,pathlib;
|
|
41
|
+
m=json.loads(pathlib.Path('reference/test_parity_matrix.json').read_text());
|
|
42
|
+
pairs={(r['r_test_file'],r['r_block_index']) for r in m};
|
|
43
|
+
py={r['python_test'] for r in m};
|
|
44
|
+
print('mapped blocks:',len(m),'unique R blocks:',len(pairs),'unique Python translations:',len(py));
|
|
45
|
+
assert len(m)==130 and len(pairs)==130 and len(py)==130"
|
|
46
|
+
|
|
47
|
+
- name: Frozen signature parity
|
|
48
|
+
run: uv run python parity/signature_audit.py --check reference/signature_parity_matrix.json
|
|
49
|
+
|
|
50
|
+
test:
|
|
51
|
+
name: Python ${{ matrix.python-version }} / ${{ matrix.os }}
|
|
52
|
+
runs-on: ${{ matrix.os }}
|
|
53
|
+
strategy:
|
|
54
|
+
fail-fast: false
|
|
55
|
+
matrix:
|
|
56
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
57
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
- uses: astral-sh/setup-uv@v6
|
|
61
|
+
with:
|
|
62
|
+
python-version: ${{ matrix.python-version }}
|
|
63
|
+
enable-cache: true
|
|
64
|
+
- name: Sync environment
|
|
65
|
+
run: uv sync --extra dev --extra time
|
|
66
|
+
- name: Run tests
|
|
67
|
+
run: uv run pytest -q
|
|
68
|
+
|
|
69
|
+
build:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
- uses: astral-sh/setup-uv@v6
|
|
74
|
+
with:
|
|
75
|
+
python-version: "3.13"
|
|
76
|
+
- name: Build distributions
|
|
77
|
+
run: uv build
|
|
78
|
+
- name: Fresh wheel smoke test
|
|
79
|
+
shell: bash
|
|
80
|
+
run: |
|
|
81
|
+
python -m venv /tmp/gp3seq-wheel-test
|
|
82
|
+
/tmp/gp3seq-wheel-test/bin/pip install dist/*.whl
|
|
83
|
+
/tmp/gp3seq-wheel-test/bin/python -c "import gp3sequencespy; print(gp3sequencespy.__version__)"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- "src/**"
|
|
10
|
+
- "pyproject.toml"
|
|
11
|
+
- ".github/workflows/docs.yml"
|
|
12
|
+
pull_request:
|
|
13
|
+
paths:
|
|
14
|
+
- "docs/**"
|
|
15
|
+
- "mkdocs.yml"
|
|
16
|
+
- "src/**"
|
|
17
|
+
- "pyproject.toml"
|
|
18
|
+
- ".github/workflows/docs.yml"
|
|
19
|
+
workflow_dispatch:
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: astral-sh/setup-uv@v6
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.13"
|
|
32
|
+
enable-cache: true
|
|
33
|
+
- name: Sync docs environment
|
|
34
|
+
run: uv sync --extra docs --extra dev --extra time
|
|
35
|
+
- name: Validate documentation contracts
|
|
36
|
+
run: uv run pytest -q tests/test_docs_contract.py
|
|
37
|
+
- name: Build documentation
|
|
38
|
+
run: uv run mkdocs build --strict
|
|
39
|
+
- name: Deploy gh-pages
|
|
40
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
41
|
+
run: uv run mkdocs gh-deploy --force
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Release checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- "v*"
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-check:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.13"
|
|
20
|
+
enable-cache: true
|
|
21
|
+
- name: Sync release environment
|
|
22
|
+
run: uv sync --extra dev --extra time --extra docs --extra release
|
|
23
|
+
- name: Validate project metadata
|
|
24
|
+
run: uv run validate-pyproject pyproject.toml
|
|
25
|
+
- name: Static quality
|
|
26
|
+
run: |
|
|
27
|
+
uv run ruff check src tests parity
|
|
28
|
+
uv run ruff format --check src tests parity
|
|
29
|
+
uv run mypy src/gp3sequencespy
|
|
30
|
+
- name: Tests and frozen contracts
|
|
31
|
+
run: |
|
|
32
|
+
uv run pytest -q
|
|
33
|
+
uv run python -c "import json,pathlib,gp3sequencespy as g; assert g.__version__ == '0.1.0'; n=[x['name'] for x in json.loads(pathlib.Path('reference/api_manifest.json').read_text())]; assert len(n)==81 and all(hasattr(g,x) and x in g.__all__ for x in n)"
|
|
34
|
+
uv run python -c "import json,pathlib; m=json.loads(pathlib.Path('reference/test_parity_matrix.json').read_text()); assert len(m)==130 and len({(r['r_test_file'],r['r_block_index']) for r in m})==130"
|
|
35
|
+
- name: Verify frozen signature matrix
|
|
36
|
+
run: uv run python parity/signature_audit.py --check reference/signature_parity_matrix.json
|
|
37
|
+
- name: Strict documentation build
|
|
38
|
+
run: uv run mkdocs build --strict
|
|
39
|
+
- name: Build distributions
|
|
40
|
+
run: uv build
|
|
41
|
+
- name: Validate distributions
|
|
42
|
+
run: uv run twine check --strict dist/*
|
|
43
|
+
- name: Verify wheel contents and metadata
|
|
44
|
+
run: >-
|
|
45
|
+
uv run python -c "import glob,zipfile; w=glob.glob('dist/*.whl'); assert len(w)==1; z=zipfile.ZipFile(w[0]); n=z.namelist(); assert any(x.endswith('.dist-info/licenses/LICENSE') for x in n); assert any(x=='gp3sequencespy/__init__.py' for x in n); print(w[0]); print('wheel files:',len(n))"
|
|
46
|
+
- name: Fresh wheel smoke test
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
python -m venv /tmp/gp3seq-release-wheel
|
|
50
|
+
wheel="$(echo dist/*.whl)"
|
|
51
|
+
/tmp/gp3seq-release-wheel/bin/pip install "${wheel}[time]"
|
|
52
|
+
/tmp/gp3seq-release-wheel/bin/python -c "import gp3sequencespy as g; assert g.__version__ == '0.1.0'; print(g.__version__); print(len(g.__all__))"
|
|
53
|
+
- uses: actions/upload-artifact@v4
|
|
54
|
+
with:
|
|
55
|
+
name: gp3sequencespy-release-candidate
|
|
56
|
+
path: dist/*
|
|
57
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python environments and caches
|
|
2
|
+
.venv/
|
|
3
|
+
venv/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.coverage
|
|
10
|
+
htmlcov/
|
|
11
|
+
|
|
12
|
+
# Build artifacts
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
|
|
17
|
+
# IDE / OS
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
|
|
23
|
+
# Local secrets
|
|
24
|
+
.env
|
|
25
|
+
.env.*
|
|
26
|
+
|
|
27
|
+
# Generated parity outputs
|
|
28
|
+
parity/actual/*
|
|
29
|
+
!parity/actual/.gitkeep
|
|
30
|
+
parity/reports/*.txt
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `gp3sequencespy` are documented here. The project is
|
|
4
|
+
currently alpha software and follows parity-first development against the frozen
|
|
5
|
+
R package `gp3sequences` 0.3.0.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
No changes yet.
|
|
10
|
+
|
|
11
|
+
## [0.1.0] - 2026-08-30
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- First non-prerelease Python release preserving all **81 / 81** frozen
|
|
16
|
+
`gp3sequences 0.3.0` public function counterparts.
|
|
17
|
+
- **130 / 130** dedicated translations of the frozen R `test_that()` blocks.
|
|
18
|
+
- Fifteen Python-native article/vignette counterparts, MkDocs documentation,
|
|
19
|
+
release governance, and multi-platform CI across Python 3.11–3.14.
|
|
20
|
+
- Machine-readable frozen API, test-block, signature, and oracle records.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Replaced the early statsmodels/Patsy time-model approximation with a validated
|
|
25
|
+
`mssm` binomial GAMM backend using penalized by-group smooths and genuine
|
|
26
|
+
participant random intercepts.
|
|
27
|
+
- Restored frozen plotting defaults and retained Matplotlib `ax=` only as a
|
|
28
|
+
keyword-only Python extension.
|
|
29
|
+
- Aligned hierarchical clustering and medoid semantics with R `hclust()`/PAM,
|
|
30
|
+
including `members=` behavior and tie-sensitive medoid scoring.
|
|
31
|
+
|
|
32
|
+
### Validation
|
|
33
|
+
|
|
34
|
+
- **182** Python tests pass locally before the release-candidate artifact freeze.
|
|
35
|
+
- Frozen API: **81 / 81**.
|
|
36
|
+
- Frozen R block ledger: **130 / 130**.
|
|
37
|
+
- Frozen public signatures: **81 / 81**, with **0 unexplained drift**.
|
|
38
|
+
- Deterministic six-contract R↔Python oracle: **PASS**.
|
|
39
|
+
- Extended clustering oracle: **3915 / 3915** partition rows and **108 / 108**
|
|
40
|
+
medoid rows matched, plus fresh `members=` oracle **PASS**.
|
|
41
|
+
- Time-model calibration: **12 / 12** `k=3/4/5 × state/transition × random-effect`
|
|
42
|
+
scenarios fit successfully within the validated R-error envelope; frozen-R
|
|
43
|
+
transition extrapolation matched to an absolute difference of approximately
|
|
44
|
+
`8.29e-06`.
|
|
45
|
+
- Exact final-version wheel and sdist must pass clean-environment artifact tests
|
|
46
|
+
before this commit can be pushed by the RC transaction.
|
|
47
|
+
|
|
48
|
+
### Deliberate parity boundaries
|
|
49
|
+
|
|
50
|
+
The stable release retains the explicitly reviewed boundaries in
|
|
51
|
+
`PARITY_EXCEPTIONS.md`: ecosystem-specific R object identity, plotting-engine
|
|
52
|
+
identity, cross-language RNG stream identity, and bit-for-bit `mgcv` identity /
|
|
53
|
+
non-default smoothing criteria are not claimed.
|
|
54
|
+
|
|
55
|
+
## [0.1.0a1] - 2026-08-29
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- 81 / 81 frozen R 0.3.0 public API counterparts.
|
|
60
|
+
- 130 / 130 frozen R `test_that()` block translations.
|
|
61
|
+
- Data validation, preparation, summaries, sequence distances, clustering,
|
|
62
|
+
consensus, motifs, transition networks, higher-order models, HMM families,
|
|
63
|
+
panel workflows, subsequence mining, inference, time-varying models, adapters,
|
|
64
|
+
audits, and visualisations.
|
|
65
|
+
- Cross-language parity harness with deterministic oracle fixtures.
|
|
66
|
+
- Ruff and mypy release-quality gates.
|
|
67
|
+
- Linux, macOS, and Windows CI on Python 3.11–3.14.
|
|
68
|
+
- Fifteen Python-native ports of the frozen R vignette set.
|
|
69
|
+
- MkDocs documentation and GitHub Pages deployment.
|
|
70
|
+
|
|
71
|
+
### Validation
|
|
72
|
+
|
|
73
|
+
- 162 tests passing before the release-readiness tranche.
|
|
74
|
+
- 81 / 81 public API contract.
|
|
75
|
+
- 130 / 130 frozen R test-block ledger.
|
|
76
|
+
- Wheel and source distribution build smoke tests.
|
|
77
|
+
|
|
78
|
+
### Known parity boundaries
|
|
79
|
+
|
|
80
|
+
See `PARITY_EXCEPTIONS.md`. API and behavioral-contract coverage do not by
|
|
81
|
+
themselves establish exact numerical parity for R RNG streams, cross-language RNG streams, ecosystem-specific adapter objects, or explicitly documented backend boundaries.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: >-
|
|
3
|
+
If you use gp3sequencespy in research, please cite the software and record
|
|
4
|
+
the exact version used.
|
|
5
|
+
title: gp3sequencespy
|
|
6
|
+
type: software
|
|
7
|
+
authors:
|
|
8
|
+
- family-names: Balaskas
|
|
9
|
+
given-names: Stefanos
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
date-released: 2026-08-30
|
|
12
|
+
license: MIT
|
|
13
|
+
repository-code: https://github.com/stefanosbalaskas/gp3sequencespy
|
|
14
|
+
url: https://stefanosbalaskas.github.io/gp3sequencespy/
|
|
15
|
+
keywords:
|
|
16
|
+
- sequence analysis
|
|
17
|
+
- scanpaths
|
|
18
|
+
- eye tracking
|
|
19
|
+
- categorical sequences
|
|
20
|
+
- reproducible research
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our standard
|
|
4
|
+
|
|
5
|
+
Participation in the `gp3sequencespy` community should be professional,
|
|
6
|
+
respectful, constructive, and focused on improving scientific software.
|
|
7
|
+
Harassment, discriminatory conduct, personal attacks, intimidation, deliberate
|
|
8
|
+
disruption, and disclosure of private information are not acceptable.
|
|
9
|
+
|
|
10
|
+
## Scientific disagreement
|
|
11
|
+
|
|
12
|
+
Technical and methodological disagreement is welcome. Critique ideas, evidence,
|
|
13
|
+
implementations, and assumptions rather than people. When a parity or statistical
|
|
14
|
+
claim is disputed, prefer a reproducible example, test, benchmark, or primary
|
|
15
|
+
source over rhetoric.
|
|
16
|
+
|
|
17
|
+
## Enforcement
|
|
18
|
+
|
|
19
|
+
Maintainers may edit, reject, lock, or remove contributions that violate these
|
|
20
|
+
standards and may restrict participation for repeated or severe violations.
|
|
21
|
+
|
|
22
|
+
## Scope
|
|
23
|
+
|
|
24
|
+
This policy applies to project repositories, issue trackers, pull requests,
|
|
25
|
+
documentation spaces, and other project-managed communication channels.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Contributing to gp3sequencespy
|
|
2
|
+
|
|
3
|
+
`gp3sequencespy` is developed parity-first against the frozen R package
|
|
4
|
+
`gp3sequences` 0.3.0. Contributions are welcome when they preserve the frozen
|
|
5
|
+
scientific contracts and make deviations explicit.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync --extra dev --extra time --extra docs --extra release
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Run the local quality gates before opening a pull request:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv run ruff check src tests parity
|
|
17
|
+
uv run ruff format --check src tests parity
|
|
18
|
+
uv run mypy src/gp3sequencespy
|
|
19
|
+
uv run pytest -q
|
|
20
|
+
uv run mkdocs build --strict
|
|
21
|
+
uv build
|
|
22
|
+
uv run twine check dist/*
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Parity rules
|
|
26
|
+
|
|
27
|
+
1. Do not change an R-corresponding public contract silently.
|
|
28
|
+
2. Add or update a parity test whenever a frozen behavior changes or is clarified.
|
|
29
|
+
3. Record deliberate R → Python ecosystem translations in `PARITY_EXCEPTIONS.md`.
|
|
30
|
+
4. Keep stochastic behavior reproducible without mutating the caller's global RNG.
|
|
31
|
+
5. Do not infer psychological, medical, biometric, or causal meaning from sequence
|
|
32
|
+
structure unless the study design and method explicitly support that inference.
|
|
33
|
+
|
|
34
|
+
## Pull requests
|
|
35
|
+
|
|
36
|
+
Keep changes focused. Describe the scientific contract affected, tests added,
|
|
37
|
+
backward-compatibility implications, and whether exact R numerical parity is
|
|
38
|
+
expected, translated, or still oracle-pending.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stefanos Balaskas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Parity exceptions and validation status
|
|
2
|
+
|
|
3
|
+
The frozen behavioral reference is **gp3sequences 0.3.0**. Python functions retain the frozen R public names, but R-specific runtime objects cannot always be represented identically in Python.
|
|
4
|
+
|
|
5
|
+
## Validated deterministic cross-language parity
|
|
6
|
+
|
|
7
|
+
The deterministic oracle was executed on Windows with **R 4.6.1** against a locally rebuilt final `gp3sequences 0.3.0` tarball from release commit `4ebf0bebea2955c5f98f8ddf0fe03e81d0b7ac3a`.
|
|
8
|
+
|
|
9
|
+
The local final tarball has archive SHA-256:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
4024a6657d4567e44615cdf87419654bd097822016c8b84bd929aa3db4dcd3a8
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
It was proven source-equivalent to the canonical frozen artifact after normalizing build-only `DESCRIPTION` fields and excluding generated build artifacts. The normalized 199-file source manifest has SHA-256:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
4dd1566e38cb20da1115fc466cc6db3b99f98413aa93876402f59221fc954e56
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The core deterministic oracle matched all six canonical CSV contracts: state summaries, transition summaries, formatted paths, motif summaries, consensus sequences, and Levenshtein distances.
|
|
22
|
+
|
|
23
|
+
The extended clustering oracle also validates R-compatible hierarchical partitions and medoids for `single`, `complete`, `average`, `mcquitty`, `median`, `centroid`, `ward.D`, and `ward.D2` across four tie-resistant fixtures and multiple `k` values, plus deterministic PAM behavior. Regression tests preserve the discovered R `hclust()` semantics.
|
|
24
|
+
|
|
25
|
+
## Explicit backend-object translations
|
|
26
|
+
|
|
27
|
+
- `as_traminer_sequences()` returns a structured wide-sequence Python adapter rather than a TraMineR `stslist` S3 object.
|
|
28
|
+
- `as_seqhmm_sequences()` returns the same structured observations tagged for the seqHMM handoff rather than an R `stslist`.
|
|
29
|
+
- `as_arules_sequences()` returns itemsets plus cSPADE-compatible `sequenceID`/`eventID` metadata rather than an R `transactions` S4 object.
|
|
30
|
+
- `as_igraph_transition_network()` returns a NetworkX graph with the corresponding edge attributes rather than an R igraph object.
|
|
31
|
+
|
|
32
|
+
These are deliberate semantic translations. Their data contracts are tested; object identity with the R backend is not claimed.
|
|
33
|
+
|
|
34
|
+
## Remaining deliberate/non-exact numerical boundaries
|
|
35
|
+
|
|
36
|
+
- **Plotting backend:** frozen plotting formals/default labels are preserved, while Python uses Matplotlib rather than base R graphics. Plot functions expose a keyword-only `ax=` target as a Python-native extension. R palette labels are mapped to Matplotlib renderers (`Viridis` → `viridis`, `Dark 3` → `tab10`). Plot-data contracts are tested; pixel-identical R graphics are not claimed.
|
|
37
|
+
- **Randomised algorithms:** NumPy and R use different random-number generators and streams. The parity target is deterministic behavior for a declared Python seed, global-RNG isolation, and equivalent statistical/algorithmic contracts—not bit-for-bit identity of cross-language random draws.
|
|
38
|
+
- **Time-varying sequence models:** the statsmodels/Patsy approximation has been replaced by `mssm` 1.2.5, using a binomial GAMM with a group main effect, separate penalized time smooths by group, and a genuine participant random intercept when requested. The documented `mgcv k -> mssm nk=k-1` mapping is used, with an adaptive spline degree at the frozen public minimum `k=3`. Population prediction excludes the participant random effect, as frozen R `predict.gam(..., exclude='s(.participant)')` does. Cross-language calibration covered state/transition outcomes, random effect on/off, `k=3/4/5`, and out-of-support transition prediction. This is a validated close semantic translation, not a claim of bit-for-bit `mgcv` identity. The Python backend intentionally supports the verified frozen default `method='REML'`; other `mgcv::gam()` smoothing criteria remain an explicit unsupported non-default boundary.
|
|
39
|
+
|
|
40
|
+
## Stable 0.1.0 exception review — 2026-08-30
|
|
41
|
+
|
|
42
|
+
Every remaining entry was reviewed before the 0.1.0 release-candidate freeze.
|
|
43
|
+
All are **retained deliberately**; none is an unexplained implementation gap:
|
|
44
|
+
|
|
45
|
+
1. **R ecosystem objects → Python-native adapters:** TraMineR/seqHMM/arules/igraph
|
|
46
|
+
object identity is runtime-specific. The Python adapters preserve the tested data
|
|
47
|
+
contract and expose native Python/NetworkX structures.
|
|
48
|
+
2. **Base-R graphics → Matplotlib:** plot-data contracts, public defaults, and call
|
|
49
|
+
semantics are tested. Pixel-level identity across rendering engines is neither
|
|
50
|
+
meaningful nor claimed.
|
|
51
|
+
3. **R RNG streams → NumPy RNG streams:** declared Python seeds are deterministic and
|
|
52
|
+
global-RNG isolation/algorithmic contracts are tested; cross-language random draws
|
|
53
|
+
are not expected to be bit-for-bit identical.
|
|
54
|
+
4. **`mgcv::gam()` → `mssm` GAMM:** the frozen default REML contract is calibrated
|
|
55
|
+
cross-language, including `k=3/4/5`, state/transition outcomes, participant random
|
|
56
|
+
effects, and extrapolation. Exact penalty/coefficient identity and non-default mgcv
|
|
57
|
+
smoothing criteria are outside the validated Python contract.
|
|
58
|
+
|
|
59
|
+
These retained boundaries are compatible with a stable Python API because they are
|
|
60
|
+
explicit, tested, and arise from language/backend differences rather than silent
|
|
61
|
+
behavioral drift.
|
|
62
|
+
|
|
63
|
+
## Frozen-test translation status
|
|
64
|
+
|
|
65
|
+
All **130 / 130** frozen R `test_that()` blocks have one dedicated Python translation test. The mapping is machine-readable in `reference/test_parity_matrix.json` and human-readable in `PARITY_TEST_MATRIX.md`.
|
|
66
|
+
|
|
67
|
+
Behavioral-contract coverage, deterministic oracle coverage, and deliberate backend translations are reported separately so that one does not overstate the other.
|