A Polars expression plugin that detects MHC class I chain starts at Rust speed
Project description
polars-mhci-starts
A Polars expression plugin that answers one question quickly: does this sequence contain the start of an MHC class I chain?
An MHC class I heavy (alpha) chain has a characteristic mature N-terminus — GSHSMRY,
GDTRPRY and around a hundred allelic variants. This plugin tests, per row, whether any
of those motifs appears in a sequence. It's a byte-level substring scan in Rust, so it
runs fast enough to sweep a whole structure database in one pass.
import polars as pl
from polars_mhci_starts import has_class_i_start
df = pl.DataFrame({"seq": [
"GSHSMRYFYTSVSRPGRGEPRFIAV", # a class I alpha chain
"MAVMAPRTLLLLLSGALALTQTWAGSHSMRYFYT", # ...behind a leader peptide
"MKWVTFISLLFLFSSAYS", # serum albumin — not MHC
None,
]})
df.with_columns(hit=has_class_i_start("seq"))
┌────────────────────────────────────┬───────┐
│ seq ┆ hit │
│ --- ┆ --- │
│ str ┆ bool │
╞════════════════════════════════════╪═══════╡
│ GSHSMRYFYTSVSRPGRGEPRFIAV ┆ true │
│ MAVMAPRTLLLLLSGALALTQTWAGSHSMRYFYT ┆ true │ start sits after the leader
│ MKWVTFISLLFLFSSAYS ┆ false │ no class I motif
│ null ┆ null │ missing is unknown, not "no match"
└────────────────────────────────────┴───────┘
Install
uv add polars-mhci-starts
# or: pip install polars-mhci-starts
Wheels are published for Linux (x86_64, aarch64), macOS (x86_64, arm64) and Windows (x64), so there's nothing to compile — you don't need a Rust toolchain to use this.
Requires Python ≥ 3.14 and Polars ≥ 1.42. The wheels are abi3-py314: one wheel per
platform covers 3.14 and every later 3.x.
To build from source instead, you'll need a Rust toolchain and uv:
git clone https://github.com/drchristhorpe/polars-mhci-starts
cd polars-mhci-starts
uv sync # fetches Python 3.14, builds the Rust extension
uv run maturin develop --release
uv run pytest
Usage
has_class_i_start takes a column name or an expression and returns a boolean
expression. Use it anywhere an expression goes — select, with_columns, filter,
lazy or eager:
df.filter(has_class_i_start("seq")) # keep only sequences with a start
df.with_columns(hit=has_class_i_start(pl.col("seq"))) # flag them instead
lf.filter(has_class_i_start("seq")).collect() # works lazily too
There is also a .mhci namespace, if you prefer method chaining:
df.with_columns(hit=pl.col("seq").mhci.has_class_i_start())
What counts as a match
A sequence matches when any catalogued class I alpha chain-start motif appears as a substring — not only at the very beginning. In a full-length precursor the mature start sits after a signal/leader peptide, and in engineered single-chain constructs it can sit much deeper still:
- Single-chain trimers (SCTs) — peptide–linker–β2m–linker–heavy chain fused into one polypeptide, so the heavy-chain start follows the peptide and the whole of β2m.
- SMART-HLA — a truncated heavy chain preceded by a designed domain that replaces α3 and β2m, so the α1 start motif again sits after an engineered N-terminal segment.
A prefix test (starts_with) would miss all of these; a substring test finds the start
wherever it has ended up.
To tolerate structures that are missing the first residue or two of the mature molecule,
each motif is tried three ways: at full length, with its first residue dropped, and with
its first two dropped. So GDTRPRY, DTRPRY and TRPRY all count as the same start.
The motif list is exposed as CLASS_I_STARTS:
from polars_mhci_starts import CLASS_I_STARTS
len(CLASS_I_STARTS) # 118 unique motifs
CLASS_I_STARTS[0] # 'GDTRPRY'
What it catches, and what it doesn't
The catalogue is built from real heavy chains, so it behaves sensibly on the wider MHC superfamily. A few worked examples, all verified in the test suite:
| Molecule | UniProt | Result | Why |
|---|---|---|---|
| HLA-A (classical class I) | P04439 | ✅ match | mature start GSHSMRY |
| CD1a (class I-like, lipid antigen) | P06126 | ✅ match | start EPLSFHV is catalogued |
| MR1 (class I-related) | Q95460 | ✅ match | start RTHSLRY is catalogued |
| HLA-DRA (class II alpha) | P01903 | ❌ no match | different N-terminus |
| HLA-DRB1 (class II beta) | P01911 | ❌ no match | starts GDTRPRF |
Class I and class II share a common ancestor and the same domain architecture, which makes
the class II chains a genuinely hard negative control rather than an easy one — HLA-DRB1
opens GDTRPRF, a single residue away from the class I catalogue entry GDTRPRY. The final
position is what tells them apart, and it does. The class I-like molecules CD1a and MR1, by
contrast, carry starts that were catalogued alongside the classical alleles, so they match —
which is the right answer if you're pulling class I-fold chains out of a structure database.
Behaviour worth knowing
- Nulls propagate as null, and do not collapse to
false. A missing sequence is unknown, not a non-match — sofilter(has_class_i_start(...))drops null rows, whilewith_columns(hit=has_class_i_start(...))keeps them visible as null. - Empty and very short strings are
false: the shortest needle is a 5-mer, so nothing shorter can match. - Non-ASCII input is rejected rather than raising. The scan is a byte-level substring search, and the motifs are pure ASCII, so no byte of a multi-byte character can be mistaken for part of a motif.
How it maps to the prior art
This packages the match_class_i_start function from an internal localpdb querying
script into a reusable, vectorised Polars expression. That function looped the motif list
per sequence in Python and returned the matched motif; here we answer the boolean form of
the same question — is a start present? — across a whole column at Rust speed. The motif
data is the same chain_starts.json.
Related
- polars-is-peptide — the sibling plugin this is modelled on: is a string a valid peptide sequence?
Licence
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polars_mhci_starts-0.1.0.tar.gz.
File metadata
- Download URL: polars_mhci_starts-0.1.0.tar.gz
- Upload date:
- Size: 41.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba30178fd8cb7da77af1315d9f2705b6e5006bb87f4a7a164e756359d199fb5c
|
|
| MD5 |
4c2dd885d8b1520ac8efe9d3398e52c4
|
|
| BLAKE2b-256 |
49bccf2f77a2b5dd8e6d9351d4246b339d0a20eeede13a19f4bbfe8c6f184e10
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0.tar.gz:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0.tar.gz -
Subject digest:
ba30178fd8cb7da77af1315d9f2705b6e5006bb87f4a7a164e756359d199fb5c - Sigstore transparency entry: 2191614768
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polars_mhci_starts-0.1.0-cp314-abi3-win_amd64.whl.
File metadata
- Download URL: polars_mhci_starts-0.1.0-cp314-abi3-win_amd64.whl
- Upload date:
- Size: 3.9 MB
- Tags: CPython 3.14+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b0ace8cd09fbb9c085d321ea4b5701d8e8216229d8f4114412aa4b15192e1af
|
|
| MD5 |
08c781077be002abb8988f9fa97bdb86
|
|
| BLAKE2b-256 |
9cdc7ac097eff3bd82d67d9afc40769b6c044a6da74d927ae60a80a85add20a5
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0-cp314-abi3-win_amd64.whl:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0-cp314-abi3-win_amd64.whl -
Subject digest:
9b0ace8cd09fbb9c085d321ea4b5701d8e8216229d8f4114412aa4b15192e1af - Sigstore transparency entry: 2191614907
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.14+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35332e93ff18527a6a02eccecc9177cc23f5e163e7a68d972e9640ab6bfc2570
|
|
| MD5 |
f6ed955ca82accd0b8b729606e143555
|
|
| BLAKE2b-256 |
56ac37a771f81d9deb6ee71ea86e5d0f93e504c394c2539a0f90007f5a643bf1
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
35332e93ff18527a6a02eccecc9177cc23f5e163e7a68d972e9640ab6bfc2570 - Sigstore transparency entry: 2191615029
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.14+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3603353f629f742585fec7714dc7a739c763f824e7d0e0e75b40ae56b76e25c0
|
|
| MD5 |
e7436ac2673150a02007979ede7eb91d
|
|
| BLAKE2b-256 |
300b11f18b00fee8f1f2a7a98ea4ef7a84a284a7398e8abe8b18bd6b82ecff0c
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0-cp314-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
3603353f629f742585fec7714dc7a739c763f824e7d0e0e75b40ae56b76e25c0 - Sigstore transparency entry: 2191614958
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polars_mhci_starts-0.1.0-cp314-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: polars_mhci_starts-0.1.0-cp314-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.1 MB
- Tags: CPython 3.14+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a384dae0720030654be0d06875755804d17d46ac4a9822b1f8e8b11750bfe62
|
|
| MD5 |
2e477ce75ff510217a8f68feafbac7a3
|
|
| BLAKE2b-256 |
d264f2701c65067bacd7c103ba0ea743c2f1eeb87ec4af560563ada9d036a27c
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0-cp314-abi3-macosx_11_0_arm64.whl:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0-cp314-abi3-macosx_11_0_arm64.whl -
Subject digest:
7a384dae0720030654be0d06875755804d17d46ac4a9822b1f8e8b11750bfe62 - Sigstore transparency entry: 2191615093
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polars_mhci_starts-0.1.0-cp314-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: polars_mhci_starts-0.1.0-cp314-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.14+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5db478185b2f9bc2abdd29ccd8ccb0818146b28dddc7adb534e52dbacad5bf7
|
|
| MD5 |
0b67a2dfe3428a01569664f1089d1a6e
|
|
| BLAKE2b-256 |
6dbbeaa15af0ce4ea0966f24adde443d903618dd28f7716e2f18cffc0b9eaeef
|
Provenance
The following attestation bundles were made for polars_mhci_starts-0.1.0-cp314-abi3-macosx_10_12_x86_64.whl:
Publisher:
CI.yml on drchristhorpe/polars-mhci-starts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_mhci_starts-0.1.0-cp314-abi3-macosx_10_12_x86_64.whl -
Subject digest:
f5db478185b2f9bc2abdd29ccd8ccb0818146b28dddc7adb534e52dbacad5bf7 - Sigstore transparency entry: 2191614841
- Sigstore integration time:
-
Permalink:
drchristhorpe/polars-mhci-starts@4e5c7f6f913f53b006307d6725a9306bde367100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/drchristhorpe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
CI.yml@4e5c7f6f913f53b006307d6725a9306bde367100 -
Trigger Event:
push
-
Statement type: