roxylib 0.2.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 (126) hide show
  1. roxylib-0.2.0/.github/workflows/examples.yml +30 -0
  2. roxylib-0.2.0/.github/workflows/pre-commit.yml +17 -0
  3. roxylib-0.2.0/.github/workflows/publish-pypi.yml +48 -0
  4. roxylib-0.2.0/.github/workflows/tests.yml +34 -0
  5. roxylib-0.2.0/.gitignore +36 -0
  6. roxylib-0.2.0/AGENTS.md +37 -0
  7. roxylib-0.2.0/DEVELOPMENT.md +52 -0
  8. roxylib-0.2.0/LICENSE +21 -0
  9. roxylib-0.2.0/PKG-INFO +154 -0
  10. roxylib-0.2.0/README.md +123 -0
  11. roxylib-0.2.0/examples/basic_api.py +30 -0
  12. roxylib-0.2.0/examples/cli_roundtrip.py +91 -0
  13. roxylib-0.2.0/examples/configured_descriptors.py +50 -0
  14. roxylib-0.2.0/examples/run_ci_examples.sh +6 -0
  15. roxylib-0.2.0/prek.toml +48 -0
  16. roxylib-0.2.0/pyproject.toml +124 -0
  17. roxylib-0.2.0/roxy/__init__.py +26 -0
  18. roxylib-0.2.0/roxy/cli/__init__.py +7 -0
  19. roxylib-0.2.0/roxy/cli/_utils.py +24 -0
  20. roxylib-0.2.0/roxy/cli/compute.py +167 -0
  21. roxylib-0.2.0/roxy/cli/describe_descriptor.py +101 -0
  22. roxylib-0.2.0/roxy/cli/init_config.py +61 -0
  23. roxylib-0.2.0/roxy/cli/list_descriptors.py +78 -0
  24. roxylib-0.2.0/roxy/cli/main.py +65 -0
  25. roxylib-0.2.0/roxy/core/__init__.py +17 -0
  26. roxylib-0.2.0/roxy/core/constants.py +450 -0
  27. roxylib-0.2.0/roxy/core/exceptions.py +17 -0
  28. roxylib-0.2.0/roxy/core/io.py +140 -0
  29. roxylib-0.2.0/roxy/data/__init__.py +1 -0
  30. roxylib-0.2.0/roxy/data/aaindex.csv +567 -0
  31. roxylib-0.2.0/roxy/descriptors/__init__.py +22 -0
  32. roxylib-0.2.0/roxy/descriptors/_utils.py +284 -0
  33. roxylib-0.2.0/roxy/descriptors/aaindex/__init__.py +5 -0
  34. roxylib-0.2.0/roxy/descriptors/aaindex/aaindex.py +138 -0
  35. roxylib-0.2.0/roxy/descriptors/autocorrelation/__init__.py +5 -0
  36. roxylib-0.2.0/roxy/descriptors/autocorrelation/autocorrelation.py +195 -0
  37. roxylib-0.2.0/roxy/descriptors/base.py +82 -0
  38. roxylib-0.2.0/roxy/descriptors/complexity/__init__.py +11 -0
  39. roxylib-0.2.0/roxy/descriptors/complexity/entropy_complexity.py +166 -0
  40. roxylib-0.2.0/roxy/descriptors/complexity/local_repetition.py +217 -0
  41. roxylib-0.2.0/roxy/descriptors/complexity/run_blockiness.py +128 -0
  42. roxylib-0.2.0/roxy/descriptors/composition/__init__.py +15 -0
  43. roxylib-0.2.0/roxy/descriptors/composition/aac.py +63 -0
  44. roxylib-0.2.0/roxy/descriptors/composition/compositional_bias.py +147 -0
  45. roxylib-0.2.0/roxy/descriptors/composition/dpc.py +70 -0
  46. roxylib-0.2.0/roxy/descriptors/composition/grouped.py +54 -0
  47. roxylib-0.2.0/roxy/descriptors/composition/kmer_full_alphabet.py +86 -0
  48. roxylib-0.2.0/roxy/descriptors/ctd/__init__.py +9 -0
  49. roxylib-0.2.0/roxy/descriptors/ctd/ctd_classic.py +155 -0
  50. roxylib-0.2.0/roxy/descriptors/ctd/distribution.py +130 -0
  51. roxylib-0.2.0/roxy/descriptors/hybrid/__init__.py +5 -0
  52. roxylib-0.2.0/roxy/descriptors/hybrid/family_summary.py +205 -0
  53. roxylib-0.2.0/roxy/descriptors/motif/__init__.py +13 -0
  54. roxylib-0.2.0/roxy/descriptors/motif/functional_residue_content.py +123 -0
  55. roxylib-0.2.0/roxy/descriptors/motif/pattern.py +112 -0
  56. roxylib-0.2.0/roxy/descriptors/motif/spacing.py +185 -0
  57. roxylib-0.2.0/roxy/descriptors/motif/user_regex.py +128 -0
  58. roxylib-0.2.0/roxy/descriptors/physicochemical/__init__.py +15 -0
  59. roxylib-0.2.0/roxy/descriptors/physicochemical/charge.py +172 -0
  60. roxylib-0.2.0/roxy/descriptors/physicochemical/global_basic.py +202 -0
  61. roxylib-0.2.0/roxy/descriptors/physicochemical/hydrophobicity.py +191 -0
  62. roxylib-0.2.0/roxy/descriptors/physicochemical/order_disorder.py +165 -0
  63. roxylib-0.2.0/roxy/descriptors/physicochemical/structural_propensity.py +140 -0
  64. roxylib-0.2.0/roxy/descriptors/positional/__init__.py +11 -0
  65. roxylib-0.2.0/roxy/descriptors/positional/normalized.py +122 -0
  66. roxylib-0.2.0/roxy/descriptors/positional/sliding_window.py +124 -0
  67. roxylib-0.2.0/roxy/descriptors/positional/terminal.py +116 -0
  68. roxylib-0.2.0/roxy/descriptors/pseudo/__init__.py +11 -0
  69. roxylib-0.2.0/roxy/descriptors/pseudo/pseaac.py +122 -0
  70. roxylib-0.2.0/roxy/descriptors/pseudo/qso.py +114 -0
  71. roxylib-0.2.0/roxy/descriptors/pseudo/sequence_order.py +159 -0
  72. roxylib-0.2.0/roxy/descriptors/registry.py +36 -0
  73. roxylib-0.2.0/tests/__init__.py +0 -0
  74. roxylib-0.2.0/tests/cli/__init__.py +0 -0
  75. roxylib-0.2.0/tests/cli/_helpers.py +8 -0
  76. roxylib-0.2.0/tests/cli/test_compute_cli.py +65 -0
  77. roxylib-0.2.0/tests/cli/test_concat_frames.py +43 -0
  78. roxylib-0.2.0/tests/cli/test_config.py +43 -0
  79. roxylib-0.2.0/tests/cli/test_resolve_names.py +27 -0
  80. roxylib-0.2.0/tests/cli/test_smoke.py +66 -0
  81. roxylib-0.2.0/tests/core/__init__.py +0 -0
  82. roxylib-0.2.0/tests/core/test_exceptions.py +17 -0
  83. roxylib-0.2.0/tests/core/test_io.py +83 -0
  84. roxylib-0.2.0/tests/descriptors/__init__.py +0 -0
  85. roxylib-0.2.0/tests/descriptors/_helpers.py +23 -0
  86. roxylib-0.2.0/tests/descriptors/aaindex/__init__.py +0 -0
  87. roxylib-0.2.0/tests/descriptors/aaindex/test_aaindex.py +63 -0
  88. roxylib-0.2.0/tests/descriptors/autocorrelation/__init__.py +0 -0
  89. roxylib-0.2.0/tests/descriptors/autocorrelation/test_autocorrelation.py +57 -0
  90. roxylib-0.2.0/tests/descriptors/complexity/__init__.py +0 -0
  91. roxylib-0.2.0/tests/descriptors/complexity/test_entropy_complexity.py +59 -0
  92. roxylib-0.2.0/tests/descriptors/complexity/test_local_repetition.py +52 -0
  93. roxylib-0.2.0/tests/descriptors/complexity/test_run_blockiness.py +53 -0
  94. roxylib-0.2.0/tests/descriptors/composition/__init__.py +0 -0
  95. roxylib-0.2.0/tests/descriptors/composition/test_aac.py +50 -0
  96. roxylib-0.2.0/tests/descriptors/composition/test_compositional_bias.py +50 -0
  97. roxylib-0.2.0/tests/descriptors/composition/test_dpc.py +47 -0
  98. roxylib-0.2.0/tests/descriptors/composition/test_grouped.py +42 -0
  99. roxylib-0.2.0/tests/descriptors/composition/test_kmer_full_alphabet.py +55 -0
  100. roxylib-0.2.0/tests/descriptors/conftest.py +30 -0
  101. roxylib-0.2.0/tests/descriptors/ctd/__init__.py +0 -0
  102. roxylib-0.2.0/tests/descriptors/ctd/test_ctd_classic.py +68 -0
  103. roxylib-0.2.0/tests/descriptors/ctd/test_distribution.py +57 -0
  104. roxylib-0.2.0/tests/descriptors/hybrid/__init__.py +0 -0
  105. roxylib-0.2.0/tests/descriptors/hybrid/test_family_summary.py +44 -0
  106. roxylib-0.2.0/tests/descriptors/motif/__init__.py +0 -0
  107. roxylib-0.2.0/tests/descriptors/motif/test_functional_residue_content.py +54 -0
  108. roxylib-0.2.0/tests/descriptors/motif/test_pattern.py +55 -0
  109. roxylib-0.2.0/tests/descriptors/motif/test_spacing.py +60 -0
  110. roxylib-0.2.0/tests/descriptors/motif/test_user_regex.py +56 -0
  111. roxylib-0.2.0/tests/descriptors/physicochemical/__init__.py +0 -0
  112. roxylib-0.2.0/tests/descriptors/physicochemical/test_charge.py +57 -0
  113. roxylib-0.2.0/tests/descriptors/physicochemical/test_global_basic.py +73 -0
  114. roxylib-0.2.0/tests/descriptors/physicochemical/test_hydrophobicity.py +55 -0
  115. roxylib-0.2.0/tests/descriptors/physicochemical/test_order_disorder.py +52 -0
  116. roxylib-0.2.0/tests/descriptors/physicochemical/test_structural_propensity.py +59 -0
  117. roxylib-0.2.0/tests/descriptors/positional/__init__.py +0 -0
  118. roxylib-0.2.0/tests/descriptors/positional/test_normalized.py +65 -0
  119. roxylib-0.2.0/tests/descriptors/positional/test_sliding_window.py +50 -0
  120. roxylib-0.2.0/tests/descriptors/positional/test_terminal.py +55 -0
  121. roxylib-0.2.0/tests/descriptors/pseudo/__init__.py +0 -0
  122. roxylib-0.2.0/tests/descriptors/pseudo/test_pseaac.py +50 -0
  123. roxylib-0.2.0/tests/descriptors/pseudo/test_qso.py +36 -0
  124. roxylib-0.2.0/tests/descriptors/pseudo/test_sequence_order.py +53 -0
  125. roxylib-0.2.0/tests/descriptors/test_registry_metadata.py +76 -0
  126. roxylib-0.2.0/uv.lock +867 -0
@@ -0,0 +1,30 @@
1
+ name: examples
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - "roxy/**"
7
+ - "examples/**"
8
+ - "pyproject.toml"
9
+ - "uv.lock"
10
+ - ".github/workflows/examples.yml"
11
+ pull_request:
12
+ paths:
13
+ - "roxy/**"
14
+ - "examples/**"
15
+ - "pyproject.toml"
16
+ - "uv.lock"
17
+ - ".github/workflows/examples.yml"
18
+
19
+ jobs:
20
+ examples:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: astral-sh/setup-uv@v5
25
+ with:
26
+ python-version: "3.12"
27
+ - name: Install dependencies
28
+ run: uv sync --all-extras
29
+ - name: Run examples
30
+ run: bash examples/run_ci_examples.sh
@@ -0,0 +1,17 @@
1
+ name: pre-commit
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ prek:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: astral-sh/setup-uv@v5
13
+ with:
14
+ python-version: "3.12"
15
+ - name: Install dependencies
16
+ run: uv sync --all-extras
17
+ - uses: j178/prek-action@v2
@@ -0,0 +1,48 @@
1
+ name: publish-pypi
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: publish-pypi-${{ github.ref }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ build:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: astral-sh/setup-uv@v5
22
+ with:
23
+ python-version: "3.12"
24
+ - name: Build distributions
25
+ run: uv build
26
+ - name: Upload distributions
27
+ uses: actions/upload-artifact@v4
28
+ with:
29
+ name: python-package-distributions
30
+ path: dist/
31
+
32
+ publish:
33
+ if: startsWith(github.ref, 'refs/tags/v')
34
+ needs: build
35
+ runs-on: ubuntu-latest
36
+ environment:
37
+ name: pypi
38
+ url: https://pypi.org/p/roxylib
39
+ permissions:
40
+ id-token: write
41
+ steps:
42
+ - name: Download distributions
43
+ uses: actions/download-artifact@v4
44
+ with:
45
+ name: python-package-distributions
46
+ path: dist/
47
+ - name: Publish package distributions to PyPI
48
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,34 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - "roxy/**"
7
+ - "tests/**"
8
+ - "pyproject.toml"
9
+ - "uv.lock"
10
+ - ".github/workflows/tests.yml"
11
+ pull_request:
12
+ paths:
13
+ - "roxy/**"
14
+ - "tests/**"
15
+ - "pyproject.toml"
16
+ - "uv.lock"
17
+ - ".github/workflows/tests.yml"
18
+
19
+ jobs:
20
+ tests:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v5
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - name: Install dependencies
32
+ run: uv sync --all-extras
33
+ - name: Run tests
34
+ run: uv run pytest -q
@@ -0,0 +1,36 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+ env/
13
+
14
+ # Testing & coverage
15
+ .pytest_cache/
16
+ .coverage
17
+ .coverage.*
18
+ htmlcov/
19
+
20
+ # Tools
21
+ .ruff_cache/
22
+ .mypy_cache/
23
+
24
+ # uv
25
+ .uv-cache/
26
+ .uv_cache/
27
+
28
+ # Jupyter
29
+ .ipynb_checkpoints/
30
+
31
+ # IDEs
32
+ .idea/
33
+ .vscode/
34
+
35
+ # OS
36
+ .DS_Store
@@ -0,0 +1,37 @@
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to AI agents when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ **Roxy** is a Python library for computing classical protein sequence descriptors for machine learning workflows. It sits between:
8
+
9
+ - **Sylphy** (sequence encoders and embeddings) — parallel; Roxy does NOT duplicate Sylphy's one-hot/ordinal/k-mers/FFT encoders
10
+
11
+ **Roxy scope**: classical descriptors only. Input: amino-acid sequences (strings). Output: `polars.DataFrame` of numerical features.
12
+
13
+ This project uses `uv` and `taskipy` — see `DEVELOPMENT.md` for setup and task commands.
14
+
15
+ ## Descriptor Architecture
16
+
17
+ New descriptor families follow this pattern:
18
+
19
+ ```python
20
+ from roxy.descriptors import BaseDescriptor, register
21
+
22
+ @register("aac", family="composition")
23
+ class AACDescriptor(BaseDescriptor):
24
+ def compute_one(self, sequence: str) -> dict[str, float]:
25
+ ...
26
+ ```
27
+
28
+ - `compute_one` returns unprefixed feature names (`{"A": 0.05, "C": 0.02, ...}`).
29
+ - `compute(sequences, ids=...)` calls `compute_one` per sequence and returns a DataFrame with columns prefixed by `{name}_`.
30
+ - Register families by importing the module in `descriptors/__init__.py`.
31
+
32
+ ## Key Invariants
33
+
34
+ - Descriptors must be stateless or only hold configuration (no mutable global state).
35
+ - `compute_one` must handle empty or non-standard sequences gracefully (return NaN, not raise).
36
+ - Never import EDA, projection, or visualisation libraries — those are out of scope.
37
+ - AAIndex CSV is bundled in `roxy/data/aaindex.csv` and loaded via `importlib.resources`. No download or cache path needed.
@@ -0,0 +1,52 @@
1
+ # Development Guide
2
+
3
+ ## Prerequisites
4
+
5
+ - Python 3.11–3.14
6
+ - [uv](https://docs.astral.sh/uv/) (package manager)
7
+
8
+ ## Setup
9
+
10
+ ```bash
11
+ git clone https://github.com/ProteinEngineering-PESB2/roxy_library
12
+ cd roxy_library
13
+ uv sync --all-extras
14
+ ```
15
+
16
+ ## Common Tasks
17
+
18
+ ```bash
19
+ uv run task format # sort imports + ruff format
20
+ uv run task lint # ruff check (no fixes)
21
+ uv run task lint-fix # ruff check --fix
22
+ uv run task test # pytest -q
23
+ uv run task test-v # pytest -v
24
+ uv run task test-cov # pytest + HTML coverage report
25
+ ```
26
+
27
+ ## Running the CLI
28
+
29
+ ```bash
30
+ uv run roxy --version
31
+ uv run roxy --help
32
+ uv run roxy list
33
+ ```
34
+
35
+ ## Adding a Descriptor Family
36
+
37
+ 1. Create `roxy/descriptors/<family_name>/<module>.py`.
38
+ 2. Implement a class inheriting `BaseDescriptor` and decorate with `@register`.
39
+ 3. Import the module in `roxy/descriptors/__init__.py` so the decorator fires.
40
+ 4. Add tests in `tests/descriptors/<family_name>/`.
41
+
42
+ See `AGENTS.md` for the full list of families and their source notebooks in `dev_notebooks/`.
43
+
44
+ ## Project Structure
45
+
46
+ See `AGENTS.md` for the full package layout.
47
+
48
+ ## Branches
49
+
50
+ - `main` — stable releases
51
+ - `refactor/cleanup-base` — current base refactor (S1)
52
+ - `feat/descriptors-<family>` — individual descriptor families (S2/S3)
roxylib-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kren AI Lab
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.
roxylib-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.5
2
+ Name: roxylib
3
+ Version: 0.2.0
4
+ Summary: Protein sequence descriptors for machine learning.
5
+ Project-URL: Homepage, https://github.com/kren-ai-lab/roxy
6
+ Project-URL: Repository, https://github.com/kren-ai-lab/roxy
7
+ Project-URL: Issues, https://github.com/kren-ai-lab/roxy/issues
8
+ Author-email: Kren AI Lab <krenai@umag.cl>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: bioinformatics,descriptors,feature-engineering,machine-learning,proteins
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
22
+ Requires-Python: <3.15,>=3.11
23
+ Requires-Dist: numpy<3.0,>=2.4
24
+ Requires-Dist: polars>=1.40.0
25
+ Requires-Dist: pyyaml>=6.0.3
26
+ Requires-Dist: rich<16.0,>=15.0
27
+ Requires-Dist: scikit-learn<2.0,>=1.8
28
+ Requires-Dist: scipy<2.0,>=1.17
29
+ Requires-Dist: typer<1.0,>=0.27
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Roxy
33
+
34
+ [![PyPI](https://img.shields.io/pypi/v/roxylib?style=flat-square)](https://pypi.org/project/roxylib/)
35
+ [![PyVersions](https://img.shields.io/pypi/pyversions/roxylib?style=flat-square)](https://github.com/kren-ai-lab/roxylib)
36
+ [![Tests](https://img.shields.io/github/actions/workflow/status/kren-ai-lab/roxy/tests.yml?style=flat-square)](https://github.com/kren-ai-lab/roxy/actions/workflows/tests.yml)
37
+ ![License](https://img.shields.io/github/license/kren-ai-lab/roxy?style=flat-square)
38
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.21917534-blue?style=flat-square)](https://doi.org/10.5281/zenodo.21917534)
39
+
40
+ Classical protein sequence descriptors for machine learning.
41
+
42
+ Roxy computes classical numerical descriptors from amino-acid sequences and
43
+ returns tabular features as `polars.DataFrame` objects.
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ pip install roxylib
49
+ # or with uv:
50
+ uv add roxylib
51
+ ```
52
+
53
+ ## Quickstart
54
+
55
+ ```python
56
+ from roxy import read_fasta, DESCRIPTOR_REGISTRY
57
+
58
+ # Load sequences from FASTA
59
+ records = read_fasta("sequences.fasta") # [(id, seq), ...]
60
+ sequences = [seq for _, seq in records]
61
+ ids = [seq_id for seq_id, _ in records]
62
+
63
+ descriptor = DESCRIPTOR_REGISTRY["aac"]()
64
+ features = descriptor.compute(sequences, ids=ids) # polars.DataFrame
65
+ ```
66
+
67
+ For direct Python use, descriptors are importable by family:
68
+
69
+ ```python
70
+ from roxy.descriptors.aaindex import AAIndexDescriptor
71
+ from roxy.descriptors.composition import KmerFullAlphabetDescriptor
72
+ from roxy.descriptors.physicochemical import ChargeDescriptor
73
+
74
+ kmer = KmerFullAlphabetDescriptor(k=2)
75
+ aaindex = AAIndexDescriptor()
76
+ charge = ChargeDescriptor()
77
+
78
+ kmer_features = kmer.compute(["ACDEFGHIK"])
79
+ aaindex_features = aaindex.compute(["ACDEFGHIK"])
80
+ charge_features = charge.compute(["ACDEFGHIK"])
81
+ ```
82
+
83
+ ## CLI
84
+
85
+ ```bash
86
+ roxy --help
87
+ roxy --version
88
+
89
+ # List and inspect descriptors
90
+ roxy list
91
+ roxy list --family composition
92
+ roxy describe aac
93
+
94
+ # Compute descriptors from FASTA, CSV, or Parquet input
95
+ roxy compute sequences.fasta -d aac -d charge -o features.csv
96
+ roxy compute sequences.fasta -f composition -o composition.parquet
97
+ roxy compute sequences.csv -d aac --seq-col sequence --id-col id -o features.csv
98
+ roxy compute sequences.fasta --all -o all_features.parquet
99
+
100
+ # Generate and use a YAML config with descriptor parameters
101
+ roxy init-config -d aac -d charge -o roxy.yaml
102
+ roxy init-config -f composition -o composition.yaml
103
+ roxy init-config --all -o all_descriptors.yaml
104
+ roxy compute sequences.fasta --config roxy.yaml -o configured_features.csv
105
+ ```
106
+
107
+ `roxy compute` requires exactly one descriptor selector: `--config`, `--all`,
108
+ `--descriptor/-d`, or `--family/-f`. CSV and Parquet inputs use `sequence` as
109
+ the default sequence column; pass `--seq-col` and `--id-col` when needed.
110
+
111
+ ## Examples
112
+
113
+ The repository ships a few plain Python scripts under [`examples/`](examples):
114
+
115
+ - `examples/basic_api.py` for direct descriptor use from Python
116
+ - `examples/configured_descriptors.py` for parameterized descriptor instances
117
+ - `examples/cli_roundtrip.py` for an end-to-end CLI config and compute flow
118
+
119
+ Run them with:
120
+
121
+ ```bash
122
+ bash examples/run_ci_examples.sh
123
+ ```
124
+
125
+ ## Descriptor Families
126
+
127
+ Registry keys are the names used by `roxy compute -d`, config files, and output
128
+ column prefixes.
129
+
130
+ | Family | Descriptor keys |
131
+ |-----------------|---------------------------------------------------------------------------------------|
132
+ | aaindex | `aaindex` |
133
+ | autocorrelation | `autocorrelation` |
134
+ | complexity | `entropy_complexity`, `local_repetition`, `run_blockiness` |
135
+ | composition | `aac`, `compositional_bias`, `dpc`, `grouped`, `kmer_full_alphabet` |
136
+ | ctd | `ctd_classic`, `distribution` |
137
+ | hybrid | `family_summary` |
138
+ | motif | `functional_residue_content`, `pattern`, `spacing`, `user_regex` |
139
+ | physicochemical | `charge`, `global_basic`, `hydrophobicity`, `order_disorder`, `structural_propensity` |
140
+ | positional | `normalized`, `sliding_window`, `terminal` |
141
+ | pseudo | `pseaac`, `qso`, `sequence_order` |
142
+
143
+ ## Development
144
+
145
+ ```bash
146
+ uv sync
147
+ uv run pytest -q
148
+ uv run task lint
149
+ uv run roxy --help
150
+ ```
151
+
152
+ ## Related Projects
153
+
154
+ - [Sylphy](https://github.com/kren-ai-lab/sylphy) — sequence encoders and pretrained model embeddings
@@ -0,0 +1,123 @@
1
+ # Roxy
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/roxylib?style=flat-square)](https://pypi.org/project/roxylib/)
4
+ [![PyVersions](https://img.shields.io/pypi/pyversions/roxylib?style=flat-square)](https://github.com/kren-ai-lab/roxylib)
5
+ [![Tests](https://img.shields.io/github/actions/workflow/status/kren-ai-lab/roxy/tests.yml?style=flat-square)](https://github.com/kren-ai-lab/roxy/actions/workflows/tests.yml)
6
+ ![License](https://img.shields.io/github/license/kren-ai-lab/roxy?style=flat-square)
7
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.21917534-blue?style=flat-square)](https://doi.org/10.5281/zenodo.21917534)
8
+
9
+ Classical protein sequence descriptors for machine learning.
10
+
11
+ Roxy computes classical numerical descriptors from amino-acid sequences and
12
+ returns tabular features as `polars.DataFrame` objects.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install roxylib
18
+ # or with uv:
19
+ uv add roxylib
20
+ ```
21
+
22
+ ## Quickstart
23
+
24
+ ```python
25
+ from roxy import read_fasta, DESCRIPTOR_REGISTRY
26
+
27
+ # Load sequences from FASTA
28
+ records = read_fasta("sequences.fasta") # [(id, seq), ...]
29
+ sequences = [seq for _, seq in records]
30
+ ids = [seq_id for seq_id, _ in records]
31
+
32
+ descriptor = DESCRIPTOR_REGISTRY["aac"]()
33
+ features = descriptor.compute(sequences, ids=ids) # polars.DataFrame
34
+ ```
35
+
36
+ For direct Python use, descriptors are importable by family:
37
+
38
+ ```python
39
+ from roxy.descriptors.aaindex import AAIndexDescriptor
40
+ from roxy.descriptors.composition import KmerFullAlphabetDescriptor
41
+ from roxy.descriptors.physicochemical import ChargeDescriptor
42
+
43
+ kmer = KmerFullAlphabetDescriptor(k=2)
44
+ aaindex = AAIndexDescriptor()
45
+ charge = ChargeDescriptor()
46
+
47
+ kmer_features = kmer.compute(["ACDEFGHIK"])
48
+ aaindex_features = aaindex.compute(["ACDEFGHIK"])
49
+ charge_features = charge.compute(["ACDEFGHIK"])
50
+ ```
51
+
52
+ ## CLI
53
+
54
+ ```bash
55
+ roxy --help
56
+ roxy --version
57
+
58
+ # List and inspect descriptors
59
+ roxy list
60
+ roxy list --family composition
61
+ roxy describe aac
62
+
63
+ # Compute descriptors from FASTA, CSV, or Parquet input
64
+ roxy compute sequences.fasta -d aac -d charge -o features.csv
65
+ roxy compute sequences.fasta -f composition -o composition.parquet
66
+ roxy compute sequences.csv -d aac --seq-col sequence --id-col id -o features.csv
67
+ roxy compute sequences.fasta --all -o all_features.parquet
68
+
69
+ # Generate and use a YAML config with descriptor parameters
70
+ roxy init-config -d aac -d charge -o roxy.yaml
71
+ roxy init-config -f composition -o composition.yaml
72
+ roxy init-config --all -o all_descriptors.yaml
73
+ roxy compute sequences.fasta --config roxy.yaml -o configured_features.csv
74
+ ```
75
+
76
+ `roxy compute` requires exactly one descriptor selector: `--config`, `--all`,
77
+ `--descriptor/-d`, or `--family/-f`. CSV and Parquet inputs use `sequence` as
78
+ the default sequence column; pass `--seq-col` and `--id-col` when needed.
79
+
80
+ ## Examples
81
+
82
+ The repository ships a few plain Python scripts under [`examples/`](examples):
83
+
84
+ - `examples/basic_api.py` for direct descriptor use from Python
85
+ - `examples/configured_descriptors.py` for parameterized descriptor instances
86
+ - `examples/cli_roundtrip.py` for an end-to-end CLI config and compute flow
87
+
88
+ Run them with:
89
+
90
+ ```bash
91
+ bash examples/run_ci_examples.sh
92
+ ```
93
+
94
+ ## Descriptor Families
95
+
96
+ Registry keys are the names used by `roxy compute -d`, config files, and output
97
+ column prefixes.
98
+
99
+ | Family | Descriptor keys |
100
+ |-----------------|---------------------------------------------------------------------------------------|
101
+ | aaindex | `aaindex` |
102
+ | autocorrelation | `autocorrelation` |
103
+ | complexity | `entropy_complexity`, `local_repetition`, `run_blockiness` |
104
+ | composition | `aac`, `compositional_bias`, `dpc`, `grouped`, `kmer_full_alphabet` |
105
+ | ctd | `ctd_classic`, `distribution` |
106
+ | hybrid | `family_summary` |
107
+ | motif | `functional_residue_content`, `pattern`, `spacing`, `user_regex` |
108
+ | physicochemical | `charge`, `global_basic`, `hydrophobicity`, `order_disorder`, `structural_propensity` |
109
+ | positional | `normalized`, `sliding_window`, `terminal` |
110
+ | pseudo | `pseaac`, `qso`, `sequence_order` |
111
+
112
+ ## Development
113
+
114
+ ```bash
115
+ uv sync
116
+ uv run pytest -q
117
+ uv run task lint
118
+ uv run roxy --help
119
+ ```
120
+
121
+ ## Related Projects
122
+
123
+ - [Sylphy](https://github.com/kren-ai-lab/sylphy) — sequence encoders and pretrained model embeddings
@@ -0,0 +1,30 @@
1
+ """Basic Python API example for Roxy."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from roxy import DESCRIPTOR_REGISTRY
6
+
7
+
8
+ def main() -> None:
9
+ """Compute a simple descriptor block from Python."""
10
+ sequences = [
11
+ "MKWVTFISLLFLFSSAYSRGVFRR",
12
+ "GAVLKVLTTGLPALISWIKRKRQQ",
13
+ "DDDEEEGGGSSSNNNQQQ",
14
+ ]
15
+ ids = ["albumin_like", "signal_peptide_like", "acidic_low_complexity"]
16
+
17
+ descriptor = DESCRIPTOR_REGISTRY["aac"]()
18
+ features = descriptor.compute(sequences, ids=ids)
19
+
20
+ assert features.height == 3
21
+ assert "id" in features.columns
22
+ assert "aac_length" in features.columns
23
+ assert "aac_freq_A" in features.columns
24
+
25
+ print("basic_api.py")
26
+ print(features.select(["id", "aac_length", "aac_freq_A", "aac_freq_K"]))
27
+
28
+
29
+ if __name__ == "__main__":
30
+ main()
@@ -0,0 +1,91 @@
1
+ """CLI example that writes a config and computes features from FASTA."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ import tempfile
7
+ from pathlib import Path
8
+
9
+ import polars as pl
10
+
11
+ from roxy import read_fasta
12
+
13
+ FASTA_TEXT = """>seq1
14
+ MKWVTFISLLFLFSSAYSRGVFRR
15
+ >seq2
16
+ GAVLKVLTTGLPALISWIKRKRQQ
17
+ >seq3
18
+ DDDEEEGGGSSSNNNQQQ
19
+ """
20
+
21
+
22
+ def _run(*args: str, cwd: Path) -> subprocess.CompletedProcess[str]:
23
+ return subprocess.run(
24
+ args,
25
+ cwd=cwd,
26
+ check=True,
27
+ capture_output=True,
28
+ text=True,
29
+ )
30
+
31
+
32
+ def main() -> None:
33
+ """Exercise `roxy init-config` and `roxy compute` end to end."""
34
+ repo_root = Path(__file__).resolve().parents[1]
35
+
36
+ with tempfile.TemporaryDirectory() as tmp_dir:
37
+ tmp_path = Path(tmp_dir)
38
+ fasta_path = tmp_path / "toy_sequences.fasta"
39
+ config_path = tmp_path / "toy_config.yaml"
40
+ output_path = tmp_path / "toy_features.csv"
41
+
42
+ fasta_path.write_text(FASTA_TEXT, encoding="utf-8")
43
+
44
+ _run(
45
+ "uv",
46
+ "run",
47
+ "roxy",
48
+ "init-config",
49
+ "-d",
50
+ "aac",
51
+ "-d",
52
+ "charge",
53
+ "-o",
54
+ str(config_path),
55
+ cwd=repo_root,
56
+ )
57
+
58
+ config_text = config_path.read_text(encoding="utf-8")
59
+ config_text = config_text.replace("include_counts: true", "include_counts: false")
60
+ config_path.write_text(config_text, encoding="utf-8")
61
+
62
+ _run(
63
+ "uv",
64
+ "run",
65
+ "roxy",
66
+ "compute",
67
+ str(fasta_path),
68
+ "--config",
69
+ str(config_path),
70
+ "-o",
71
+ str(output_path),
72
+ "--no-progress",
73
+ cwd=repo_root,
74
+ )
75
+
76
+ records = read_fasta(fasta_path)
77
+ df = pl.read_csv(output_path)
78
+
79
+ assert len(records) == 3
80
+ assert df.height == 3
81
+ assert "length" in df.columns
82
+ assert "aac_freq_A" in df.columns
83
+ assert "aac_count_A" not in df.columns
84
+ assert "charge_net_charge_ph5p0" in df.columns
85
+
86
+ print("cli_roundtrip.py")
87
+ print(df.select(["id", "length", "aac_freq_A", "charge_net_charge_ph5p0"]))
88
+
89
+
90
+ if __name__ == "__main__":
91
+ main()