pepcluster 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.
- pepcluster-0.1.0/.github/workflows/CI.yml +158 -0
- pepcluster-0.1.0/.gitignore +29 -0
- pepcluster-0.1.0/Cargo.lock +180 -0
- pepcluster-0.1.0/Cargo.toml +17 -0
- pepcluster-0.1.0/LICENSE +21 -0
- pepcluster-0.1.0/PKG-INFO +228 -0
- pepcluster-0.1.0/README.md +207 -0
- pepcluster-0.1.0/examples/peptides.fasta +38 -0
- pepcluster-0.1.0/pyproject.toml +42 -0
- pepcluster-0.1.0/python/pepcluster/__init__.py +54 -0
- pepcluster-0.1.0/python/pepcluster/__main__.py +6 -0
- pepcluster-0.1.0/python/pepcluster/_core.pyi +28 -0
- pepcluster-0.1.0/python/pepcluster/cli.py +60 -0
- pepcluster-0.1.0/python/pepcluster/clustering.py +666 -0
- pepcluster-0.1.0/src/lib.rs +534 -0
- pepcluster-0.1.0/tests/test_clustering.py +72 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Build cross-platform wheels with maturin and publish to PyPI on version tags.
|
|
2
|
+
#
|
|
3
|
+
# Publishing uses PyPI Trusted Publishing (OpenID Connect) — no API token or
|
|
4
|
+
# secret is stored. One-time setup: on https://pypi.org/manage/account/publishing/
|
|
5
|
+
# add a "pending publisher" with owner=AmirAsgary, repo=PepCluster, workflow=CI.yml.
|
|
6
|
+
# Then release with: `git tag v0.1.0 && git push origin v0.1.0`.
|
|
7
|
+
name: CI
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches: [main, master]
|
|
12
|
+
tags: ["v*"]
|
|
13
|
+
pull_request:
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
# PyO3 0.23 supports up to CPython 3.13, but the runners now ship 3.14.
|
|
21
|
+
# We build a single stable-ABI (abi3) wheel per platform; this flag lets the
|
|
22
|
+
# build proceed when the build interpreter is newer than PyO3's known max.
|
|
23
|
+
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
linux:
|
|
27
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
28
|
+
strategy:
|
|
29
|
+
matrix:
|
|
30
|
+
platform:
|
|
31
|
+
- runner: ubuntu-22.04
|
|
32
|
+
target: x86_64
|
|
33
|
+
- runner: ubuntu-22.04
|
|
34
|
+
target: aarch64
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.x"
|
|
40
|
+
- name: Build wheels
|
|
41
|
+
uses: PyO3/maturin-action@v1
|
|
42
|
+
with:
|
|
43
|
+
target: ${{ matrix.platform.target }}
|
|
44
|
+
args: --release --out dist
|
|
45
|
+
sccache: "true"
|
|
46
|
+
manylinux: auto
|
|
47
|
+
- name: Upload wheels
|
|
48
|
+
uses: actions/upload-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: wheels-linux-${{ matrix.platform.target }}
|
|
51
|
+
path: dist
|
|
52
|
+
|
|
53
|
+
musllinux:
|
|
54
|
+
runs-on: ubuntu-22.04
|
|
55
|
+
strategy:
|
|
56
|
+
matrix:
|
|
57
|
+
platform:
|
|
58
|
+
- target: x86_64
|
|
59
|
+
- target: aarch64
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
- uses: actions/setup-python@v5
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.x"
|
|
65
|
+
- name: Build wheels
|
|
66
|
+
uses: PyO3/maturin-action@v1
|
|
67
|
+
with:
|
|
68
|
+
target: ${{ matrix.platform.target }}
|
|
69
|
+
args: --release --out dist
|
|
70
|
+
sccache: "true"
|
|
71
|
+
manylinux: musllinux_1_2
|
|
72
|
+
- name: Upload wheels
|
|
73
|
+
uses: actions/upload-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
name: wheels-musllinux-${{ matrix.platform.target }}
|
|
76
|
+
path: dist
|
|
77
|
+
|
|
78
|
+
windows:
|
|
79
|
+
runs-on: windows-latest
|
|
80
|
+
strategy:
|
|
81
|
+
matrix:
|
|
82
|
+
platform:
|
|
83
|
+
- target: x64
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- uses: actions/setup-python@v5
|
|
87
|
+
with:
|
|
88
|
+
python-version: "3.x"
|
|
89
|
+
architecture: ${{ matrix.platform.target }}
|
|
90
|
+
- name: Build wheels
|
|
91
|
+
uses: PyO3/maturin-action@v1
|
|
92
|
+
with:
|
|
93
|
+
target: ${{ matrix.platform.target }}
|
|
94
|
+
args: --release --out dist
|
|
95
|
+
sccache: "true"
|
|
96
|
+
- name: Upload wheels
|
|
97
|
+
uses: actions/upload-artifact@v4
|
|
98
|
+
with:
|
|
99
|
+
name: wheels-windows-${{ matrix.platform.target }}
|
|
100
|
+
path: dist
|
|
101
|
+
|
|
102
|
+
macos:
|
|
103
|
+
# Both wheels build on the Apple-Silicon runner (x86_64 is cross-compiled),
|
|
104
|
+
# avoiding the deprecated / slow-to-schedule Intel macos-13 runners.
|
|
105
|
+
runs-on: macos-14
|
|
106
|
+
strategy:
|
|
107
|
+
matrix:
|
|
108
|
+
platform:
|
|
109
|
+
- target: x86_64
|
|
110
|
+
- target: aarch64
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/checkout@v4
|
|
113
|
+
- uses: actions/setup-python@v5
|
|
114
|
+
with:
|
|
115
|
+
python-version: "3.x"
|
|
116
|
+
- name: Build wheels
|
|
117
|
+
uses: PyO3/maturin-action@v1
|
|
118
|
+
with:
|
|
119
|
+
target: ${{ matrix.platform.target }}
|
|
120
|
+
args: --release --out dist
|
|
121
|
+
sccache: "true"
|
|
122
|
+
- name: Upload wheels
|
|
123
|
+
uses: actions/upload-artifact@v4
|
|
124
|
+
with:
|
|
125
|
+
name: wheels-macos-${{ matrix.platform.target }}
|
|
126
|
+
path: dist
|
|
127
|
+
|
|
128
|
+
sdist:
|
|
129
|
+
runs-on: ubuntu-22.04
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/checkout@v4
|
|
132
|
+
- name: Build sdist
|
|
133
|
+
uses: PyO3/maturin-action@v1
|
|
134
|
+
with:
|
|
135
|
+
command: sdist
|
|
136
|
+
args: --out dist
|
|
137
|
+
- name: Upload sdist
|
|
138
|
+
uses: actions/upload-artifact@v4
|
|
139
|
+
with:
|
|
140
|
+
name: wheels-sdist
|
|
141
|
+
path: dist
|
|
142
|
+
|
|
143
|
+
release:
|
|
144
|
+
name: Release
|
|
145
|
+
runs-on: ubuntu-latest
|
|
146
|
+
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
147
|
+
needs: [linux, musllinux, windows, macos, sdist]
|
|
148
|
+
permissions:
|
|
149
|
+
# Mandatory for PyPI Trusted Publishing via OpenID Connect.
|
|
150
|
+
id-token: write
|
|
151
|
+
steps:
|
|
152
|
+
- uses: actions/download-artifact@v4
|
|
153
|
+
with:
|
|
154
|
+
path: dist
|
|
155
|
+
pattern: wheels-*
|
|
156
|
+
merge-multiple: true
|
|
157
|
+
- name: Publish to PyPI
|
|
158
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Rust
|
|
2
|
+
/target
|
|
3
|
+
Cargo.lock.bak
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.so
|
|
9
|
+
*.pyd
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
.eggs/
|
|
17
|
+
|
|
18
|
+
# Virtual environments
|
|
19
|
+
.venv/
|
|
20
|
+
venv/
|
|
21
|
+
env/
|
|
22
|
+
|
|
23
|
+
# maturin
|
|
24
|
+
wheels/
|
|
25
|
+
|
|
26
|
+
# Editors / OS
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
29
|
+
.DS_Store
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "cfg-if"
|
|
13
|
+
version = "1.0.4"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "heck"
|
|
19
|
+
version = "0.5.0"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "indoc"
|
|
25
|
+
version = "2.0.7"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"rustversion",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "libc"
|
|
34
|
+
version = "0.2.183"
|
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
+
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
|
37
|
+
|
|
38
|
+
[[package]]
|
|
39
|
+
name = "memoffset"
|
|
40
|
+
version = "0.9.1"
|
|
41
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
43
|
+
dependencies = [
|
|
44
|
+
"autocfg",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "once_cell"
|
|
49
|
+
version = "1.21.4"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "pepcluster"
|
|
55
|
+
version = "0.1.0"
|
|
56
|
+
dependencies = [
|
|
57
|
+
"pyo3",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[[package]]
|
|
61
|
+
name = "portable-atomic"
|
|
62
|
+
version = "1.13.1"
|
|
63
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
64
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
65
|
+
|
|
66
|
+
[[package]]
|
|
67
|
+
name = "proc-macro2"
|
|
68
|
+
version = "1.0.106"
|
|
69
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
70
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
71
|
+
dependencies = [
|
|
72
|
+
"unicode-ident",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[[package]]
|
|
76
|
+
name = "pyo3"
|
|
77
|
+
version = "0.23.5"
|
|
78
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
79
|
+
checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872"
|
|
80
|
+
dependencies = [
|
|
81
|
+
"cfg-if",
|
|
82
|
+
"indoc",
|
|
83
|
+
"libc",
|
|
84
|
+
"memoffset",
|
|
85
|
+
"once_cell",
|
|
86
|
+
"portable-atomic",
|
|
87
|
+
"pyo3-build-config",
|
|
88
|
+
"pyo3-ffi",
|
|
89
|
+
"pyo3-macros",
|
|
90
|
+
"unindent",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "pyo3-build-config"
|
|
95
|
+
version = "0.23.5"
|
|
96
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
97
|
+
checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb"
|
|
98
|
+
dependencies = [
|
|
99
|
+
"once_cell",
|
|
100
|
+
"target-lexicon",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "pyo3-ffi"
|
|
105
|
+
version = "0.23.5"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d"
|
|
108
|
+
dependencies = [
|
|
109
|
+
"libc",
|
|
110
|
+
"pyo3-build-config",
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
[[package]]
|
|
114
|
+
name = "pyo3-macros"
|
|
115
|
+
version = "0.23.5"
|
|
116
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
117
|
+
checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da"
|
|
118
|
+
dependencies = [
|
|
119
|
+
"proc-macro2",
|
|
120
|
+
"pyo3-macros-backend",
|
|
121
|
+
"quote",
|
|
122
|
+
"syn",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[[package]]
|
|
126
|
+
name = "pyo3-macros-backend"
|
|
127
|
+
version = "0.23.5"
|
|
128
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
129
|
+
checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028"
|
|
130
|
+
dependencies = [
|
|
131
|
+
"heck",
|
|
132
|
+
"proc-macro2",
|
|
133
|
+
"pyo3-build-config",
|
|
134
|
+
"quote",
|
|
135
|
+
"syn",
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "quote"
|
|
140
|
+
version = "1.0.45"
|
|
141
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
142
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
143
|
+
dependencies = [
|
|
144
|
+
"proc-macro2",
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
[[package]]
|
|
148
|
+
name = "rustversion"
|
|
149
|
+
version = "1.0.22"
|
|
150
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
151
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
152
|
+
|
|
153
|
+
[[package]]
|
|
154
|
+
name = "syn"
|
|
155
|
+
version = "2.0.117"
|
|
156
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
157
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
158
|
+
dependencies = [
|
|
159
|
+
"proc-macro2",
|
|
160
|
+
"quote",
|
|
161
|
+
"unicode-ident",
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
[[package]]
|
|
165
|
+
name = "target-lexicon"
|
|
166
|
+
version = "0.12.16"
|
|
167
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
168
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
169
|
+
|
|
170
|
+
[[package]]
|
|
171
|
+
name = "unicode-ident"
|
|
172
|
+
version = "1.0.24"
|
|
173
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
174
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
175
|
+
|
|
176
|
+
[[package]]
|
|
177
|
+
name = "unindent"
|
|
178
|
+
version = "0.2.4"
|
|
179
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
180
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "pepcluster"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
description = "Rust backend for BLOSUM62-aware anchor-residue clustering of immunopeptides"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
repository = "https://github.com/AmirAsgary/PepCluster"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
|
|
10
|
+
[lib]
|
|
11
|
+
name = "_core"
|
|
12
|
+
crate-type = ["cdylib"]
|
|
13
|
+
|
|
14
|
+
# abi3-py38: build a single stable-ABI wheel per platform that works on
|
|
15
|
+
# CPython 3.8+ (including future versions), instead of one wheel per version.
|
|
16
|
+
[dependencies]
|
|
17
|
+
pyo3 = { version = "0.23", features = ["extension-module", "abi3-py38"] }
|
pepcluster-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amir Asgary
|
|
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,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pepcluster
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Science/Research
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Rust
|
|
9
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Summary: BLOSUM62-aware anchor-residue clustering for immunopeptides, with a Rust backend
|
|
12
|
+
Keywords: bioinformatics,immunopeptidomics,MHC,HLA,peptide,clustering,BLOSUM62
|
|
13
|
+
Author-email: Amir Asgary <amir.asgary@mpinat.mpg.de>
|
|
14
|
+
License: MIT
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Homepage, https://github.com/AmirAsgary/PepCluster
|
|
18
|
+
Project-URL: Issues, https://github.com/AmirAsgary/PepCluster/issues
|
|
19
|
+
Project-URL: Repository, https://github.com/AmirAsgary/PepCluster
|
|
20
|
+
|
|
21
|
+
# PepCluster
|
|
22
|
+
|
|
23
|
+
**BLOSUM62-aware anchor-residue clustering for immunopeptides — with a fast Rust backend.**
|
|
24
|
+
|
|
25
|
+
PepCluster groups peptides by the similarity of their MHC-I **anchor residues**
|
|
26
|
+
(the first 3 + last 3 amino acids) using a BLOSUM62-normalized similarity metric
|
|
27
|
+
with double weight on the primary anchor positions P2 and PΩ. It is built for
|
|
28
|
+
large immunopeptidomics datasets: a Rust extension does the heavy lifting
|
|
29
|
+
(10–100× faster than pure Python), and a pure-Python fallback keeps it working
|
|
30
|
+
everywhere.
|
|
31
|
+
|
|
32
|
+
Unlike general-purpose sequence tools (e.g. MMseqs2), PepCluster distinguishes
|
|
33
|
+
anchor from non-anchor positions, which is what actually drives MHC-I binding
|
|
34
|
+
specificity — producing biologically interpretable clusters on short (8–14 aa)
|
|
35
|
+
peptides where full-length estimators break down.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install pepcluster
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Prebuilt wheels are published for Linux, macOS, and Windows, so **no Rust
|
|
46
|
+
toolchain is required** for end users. If you install on a platform without a
|
|
47
|
+
wheel, pip builds from source (needs a Rust compiler — see
|
|
48
|
+
[Building from source](#building-from-source)).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
53
|
+
|
|
54
|
+
### Command line
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pepcluster -i examples/peptides.fasta -o out -t 0.6
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This writes cluster assignments and per-cluster FASTA files under `out/`
|
|
61
|
+
(see [Output files](#output-files)).
|
|
62
|
+
|
|
63
|
+
### Python
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import pepcluster
|
|
67
|
+
|
|
68
|
+
# End-to-end: FASTA in → TSV + per-cluster FASTA out
|
|
69
|
+
stats = pepcluster.cluster_fasta("peptides.fasta", "out", threshold=0.6)
|
|
70
|
+
print(stats["n_clusters"], "clusters")
|
|
71
|
+
|
|
72
|
+
# Low-level: cluster a dict of unique 6-mer anchors → frequency
|
|
73
|
+
mapping, n_cmp, n_early = pepcluster.cluster_anchors(
|
|
74
|
+
{"YLLAGV": 3, "YMLAGV": 1, "GYAWTK": 2}, 0.6)
|
|
75
|
+
# mapping: {anchor -> representative anchor}
|
|
76
|
+
|
|
77
|
+
# Optional Lloyd-style refinement on top of the greedy result
|
|
78
|
+
refined, refine_stats = pepcluster.refine_clusters(
|
|
79
|
+
{"YLLAGV": 3, "YMLAGV": 1}, mapping, 0.6, iterations=3)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`pepcluster.HAS_RUST` tells you whether the compiled backend is active
|
|
83
|
+
(`cluster_anchors` / `refine_clusters` automatically use Rust when available and
|
|
84
|
+
fall back to identical pure-Python implementations otherwise).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## CLI options
|
|
89
|
+
|
|
90
|
+
| Flag | Default | Description |
|
|
91
|
+
|------|---------|-------------|
|
|
92
|
+
| `-i, --input` | *required* | Input FASTA file |
|
|
93
|
+
| `-o, --outdir` | `anchor_clusters` | Output directory |
|
|
94
|
+
| `-t, --threshold` | `0.6` | BLOSUM similarity threshold (0.0–1.0) |
|
|
95
|
+
| `--min-cluster-size` | `2` | Min members for a per-cluster FASTA |
|
|
96
|
+
| `--n-front` | `3` | N-terminal anchor length |
|
|
97
|
+
| `--n-back` | `3` | C-terminal anchor length |
|
|
98
|
+
| `--refinement` | off | Apply Lloyd-style refinement after greedy clustering |
|
|
99
|
+
| `--iterations` | `3` | Max refinement passes (with `--refinement`) |
|
|
100
|
+
| `--backend` | `auto` | `auto` \| `rust` \| `python` |
|
|
101
|
+
| `-q, --quiet` | — | Suppress progress output |
|
|
102
|
+
|
|
103
|
+
**Threshold guide:**
|
|
104
|
+
|
|
105
|
+
| Value | Effect |
|
|
106
|
+
|-------|--------|
|
|
107
|
+
| 0.8 | Strict — mostly exact matches + very conservative substitutions |
|
|
108
|
+
| 0.6 | Moderate — allows 1–2 conservative substitutions (recommended) |
|
|
109
|
+
| 0.4 | Relaxed — broader groups for exploratory analysis |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Output files
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
out/
|
|
117
|
+
├── clusters.tsv # cluster_id, representative_anchor, header, sequence, anchor (every peptide)
|
|
118
|
+
├── cluster_summary.tsv # cluster_id, representative_anchor, size (sorted by size)
|
|
119
|
+
├── summary.txt # run statistics
|
|
120
|
+
└── fasta/
|
|
121
|
+
├── cluster_0.fasta # per-cluster FASTA, ready for MSA (>= --min-cluster-size members)
|
|
122
|
+
├── cluster_1.fasta
|
|
123
|
+
└── SHORT_peptides.fasta # peptides too short to form an anchor (if any)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## How it works
|
|
129
|
+
|
|
130
|
+
1. **Anchor extraction.** Each peptide is reduced to its 6-residue anchor: the
|
|
131
|
+
first `--n-front` (3) and last `--n-back` (3) amino acids. Peptides shorter
|
|
132
|
+
than that are set aside in `SHORT_peptides.fasta`.
|
|
133
|
+
2. **Deduplicate.** Peptides are grouped by their exact anchor, so clustering
|
|
134
|
+
operates on *unique* anchors weighted by frequency.
|
|
135
|
+
3. **Similarity metric.** Two anchors are compared position-by-position with a
|
|
136
|
+
BLOSUM62 score normalized to `sim(a,b) = B(a,b) / sqrt(B(a,a)·B(b,b))`.
|
|
137
|
+
Positions **P2 and PΩ carry 2× weight** (the primary MHC-I anchors); the
|
|
138
|
+
score is a weighted mean in `[−…, 1]`.
|
|
139
|
+
4. **Blocking.** Unique anchors are bucketed by a reduced 10-letter alphabet at
|
|
140
|
+
P2 and PΩ (10×10 = 100 bins), so only plausibly-similar anchors are ever
|
|
141
|
+
compared. High-weight positions are checked first with early termination.
|
|
142
|
+
5. **Greedy clustering.** Within each block, anchors are processed
|
|
143
|
+
most-frequent-first; each joins the first centroid above `threshold` or
|
|
144
|
+
becomes a new centroid.
|
|
145
|
+
6. **Optional refinement** (`--refinement`). A Lloyd-style pass iterates:
|
|
146
|
+
medoid update → cross-block reassignment → centroid merging, until stable.
|
|
147
|
+
|
|
148
|
+
The Rust backend (`pepcluster._core`) and the pure-Python reference
|
|
149
|
+
(`pepcluster.clustering`) implement identical logic and produce identical
|
|
150
|
+
cluster assignments; the test suite asserts this parity.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Performance
|
|
155
|
+
|
|
156
|
+
| Dataset | Python | Rust |
|
|
157
|
+
|---------|--------|------|
|
|
158
|
+
| 7K peptides | <1 s | <1 s |
|
|
159
|
+
| 2.5M peptides | ~3 min | ~15 s |
|
|
160
|
+
|
|
161
|
+
Speed comes from anchor deduplication, coarse-alphabet blocking, and weighted
|
|
162
|
+
early-termination in the similarity check.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Building from source
|
|
167
|
+
|
|
168
|
+
Requires a [Rust toolchain](https://rustup.rs) and
|
|
169
|
+
[maturin](https://www.maturin.rs).
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# one-time
|
|
173
|
+
pip install maturin
|
|
174
|
+
|
|
175
|
+
# build + install into the current environment (editable-ish)
|
|
176
|
+
maturin develop --release
|
|
177
|
+
|
|
178
|
+
# or build a wheel
|
|
179
|
+
maturin build --release # wheel lands in target/wheels/
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The project uses maturin's mixed layout: Rust lives in `src/lib.rs`
|
|
183
|
+
(compiled to `pepcluster._core`), Python in `python/pepcluster/`.
|
|
184
|
+
|
|
185
|
+
Run the tests with:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pip install pytest
|
|
189
|
+
pytest
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Releasing (maintainers)
|
|
195
|
+
|
|
196
|
+
Wheels are built for Linux / macOS / Windows by
|
|
197
|
+
[`.github/workflows/CI.yml`](.github/workflows/CI.yml) and published to PyPI on
|
|
198
|
+
version tags via [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
|
|
199
|
+
(OpenID Connect — no API token or stored secret).
|
|
200
|
+
|
|
201
|
+
1. One-time: on <https://pypi.org/manage/account/publishing/> add a pending
|
|
202
|
+
publisher — Owner `AmirAsgary`, Repository `PepCluster`, Workflow `CI.yml`
|
|
203
|
+
(leave the environment blank).
|
|
204
|
+
2. Bump the version in `pyproject.toml` **and** `Cargo.toml`.
|
|
205
|
+
3. Tag and push:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
git tag v0.1.0
|
|
209
|
+
git push origin v0.1.0
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The `release` job then builds all wheels + an sdist and uploads them to PyPI.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
[MIT](LICENSE) © 2026 Amir Asgary
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Citation
|
|
223
|
+
|
|
224
|
+
If you use PepCluster in your research, please cite this repository:
|
|
225
|
+
|
|
226
|
+
> Asgary, A. *PepCluster: BLOSUM62-aware anchor-residue clustering for
|
|
227
|
+
> immunopeptides.* https://github.com/AmirAsgary/PepCluster
|
|
228
|
+
|