Metadata-Version: 2.4
Name: DeepMutSim
Version: 1.2.0
Summary: Enumerate all possible SNVs for MANE transcripts using HGVS nomenclature.
Author-email: Liu Sun <sunliu@yxnu.edu.cn>, Jian Yang <yangjian@yxnu.edu.cn>
License-Expression: MIT
Project-URL: Homepage, https://github.com/liu-sun/DeepMutSim
Project-URL: Issues, https://github.com/liu-sun/DeepMutSim/issues
Project-URL: Repository, https://github.com/liu-sun/DeepMutSim
Keywords: bioinformatics,hgvs,variant,mane,ncbi,entrez,mutation
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: biopython
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-cov>=4.0; extra == "test"
Dynamic: license-file

# DeepMutSim

Generate all possible single nucleotide variants (SNVs) for MANE transcripts
using [HGVS nomenclature][hgvs].  DeepMutSim queries NCBI Entrez to fetch the
MANE Select / MANE Plus Clinical transcript for any human gene and enumerates
every possible substitution — coding, UTR, splice sites, and protein-level.

[hgvs]: https://varnomen.hgvs.org/

## Features

All variants carry their genomic (chromosome) coordinate as an extra `g.` HGVS
element.  For example `cds("G6PD")` returns `(c.HGVS, p.1letter, p.3letter,
g.HGVS)` where `g.HGVS` is an `NC_`-based coordinate such as
`NC_000023.11:g.154534419G>A`.

| Function | Output | Description |
|---|---|---|
| `cds(gene)` | `list[tuple]` | All CDS SNVs: `(c, p.1letter, p.3letter, g)` |
| `missense(gene)` | `list[tuple]` | Missense variants: `(c, p.1letter, p.3letter, g)` |
| `codon_sub(gene)` | `list[tuple]` | All codon substitutions: `(c, g)` |
| `aa_sub(gene)` | `list[tuple]` | All single amino-acid substitutions: `(p.1letter, p.3letter)` |
| `utr5(gene)` | `list[tuple]` | All 5' UTR SNVs: `(c, g)` |
| `utr3(gene)` | `list[tuple]` | All 3' UTR SNVs: `(c, g)` |
| `splice_site(gene)` | `list[tuple]` | Canonical donor/acceptor ±1, ±2: `(c, g)` |
| `ss(gene)` | `list[tuple]` | Splice-region SNVs (5'ss −3…+8, 3'ss −20…+3): `(c, g)` |

## Genomic coordinates

Every variant carries its genomic (chromosome) position as a **`g.` HGVS**
string anchored to the primary-assembly RefSeq accession (e.g.
`NC_000011.10:g.2160971T>C`).  Coordinates are computed by `GenomicMapper`,
which:

- maps the MANE transcript's exons onto the fetched chromosome region by exact
  sequence match, and
- applies **strand-aware reverse-complementation**: for minus-strand genes the
  transcript reference/alternate bases are complemented to the genomic (plus)
  strand, and the coordinate direction is reversed.

For example, on minus-strand `INS`, the coding change `c.1A>G` is reported as
`NC_000011.10:g.2160971T>C` (the transcript `A` maps to `T` on the plus
strand).  For plus-strand genes such as `ADAMTS13`, bases are unchanged
(`c.1A>G` → `NC_000009.12:g.133422444A>G`).  See [Validation](#validation)
for the genes used to verify this mapping against the reference assembly.

## Installation

```bash
pip install deepmutsim
```

DeepMutSim requires Python ≥3.8 and [Biopython][biopython].

[biopython]: https://biopython.org/

## Configuration

Two environment variables are **optional** for NCBI Entrez access:

| Variable | Required | Description |
|---|---|---|
| `EMAIL` | Recommended | Your email address (NCBI policy) |
| `API_KEY` | Optional | NCBI API key — raises the rate limit from 3 to 10 req/s |

Both are read once at import time by `_configure_entrez()`.  When a variable is
unset, the corresponding `Bio.Entrez` attribute is left as `None`.

[Obtain an API key][ncbi-key] from your NCBI account settings.

[ncbi-key]: https://ncbiinsights.ncbi.nlm.nih.gov/2017/11/02/new-api-keys-for-the-e-utilities/

**Linux / macOS:**

```bash
export EMAIL="your.email@example.com"
export API_KEY="your_api_key_here"
```

**Windows (PowerShell):**

```powershell
$env:EMAIL = "your.email@example.com"
$env:API_KEY = "your_api_key_here"
```

## Quick start

```python
import deepmutsim

# All CDS single-nucleotide variants
variants = deepmutsim.cds("INS")
# [('NM_000207.3:c.1A>G', 'NP_000198.1:p.(M1?)', 'NP_000198.1:p.(Met1?)',
#   'NC_000011.10:g.2160971T>C'), ...]

# All missense variants
missense = deepmutsim.missense("TP53")

# All 5' UTR SNVs
utr5_vars = deepmutsim.utr5("BRCA1")

# All canonical splice site variants
splice = deepmutsim.splice_site("CFTR")
```

## API reference

### Query helpers

- **`nm(gene, mane="MANE Select")`** — Fetch the MANE nucleotide record (GenBank).
- **`np(gene, mane="MANE Select")`** — Fetch the MANE protein record (FASTA).
- **`nc(gene)`** — Fetch the primary assembly RefSeq accession.
- **`refseqgene(gene)`** — Fetch the RefSeqGene (NG_) genomic record (introns included).
- **`gene_genomic_info(gene)`** — Gene's chromosome location (accession, strand, span).
- **`chromosome_region(gene)`** — Chromosome sequence covering the gene.
- **`GenomicMapper(gene)`** — Transcript → chromosome coordinate mapper.

Every variant-generating function accepts an optional `mane` argument
(`"MANE Select"`, the default, or `"MANE Plus Clinical"`) to select the MANE
transcript set.  This avoids multiple-match `ValueError`s for genes such as
`CDKN2A` that have transcripts in both sets.

### CDS variants

- **`cds(gene, mane="MANE Select")`** → `list[tuple[str, str, str, str]]`
  Every possible single-nucleotide substitution across the coding sequence.
  Each entry is `(c.HGVS, p.HGVS_1letter, p.HGVS_3letter, g.HGVS)`.  The
  initiator methionine is always reported as `M1?` / `Met1?`.  The terminal
  stop codon is excluded (see [Design notes](#design-notes)).

- **`missense(gene, mane="MANE Select")`** → `list[tuple[str, str, str, str]]`
  Codon substitutions that change the encoded amino acid to a *different*
  amino acid.  Synonymous (silent) and nonsense (stop-gain) changes are
  excluded — use `codon_sub()` for the full set.  Includes multi-base changes
  (reported as `delins`).  Same tuple format as `cds()`.

- **`codon_sub(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  All possible codon substitutions — silent, missense, and nonsense
  (stop-gain).  The terminal stop codon is excluded (see
  [Design notes](#design-notes)).  Single-base changes use `X>Y` notation;
  multi-base changes use `delins`.  Each entry is `(c.HGVS, g.HGVS)`.

### UTR variants

- **`utr5(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  All SNVs in the 5' untranslated region.  Positions use negative HGVS
  numbering (`c.-59`, `c.-58`, …, `c.-1`).  Each entry is `(c.HGVS, g.HGVS)`.

- **`utr3(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  All SNVs in the 3' untranslated region.  Positions use `c.*` numbering
  (`c.*1`, `c.*2`, …).  Each entry is `(c.HGVS, g.HGVS)`.

### Splice site variants

- **`splice_site(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  Canonical donor (+1, +2) and acceptor (−2, −1) positions of every intron
  within the CDS boundaries.  Each entry is `(c.HGVS, g.HGVS)`.

- **`ss(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  All SNVs in the splice-site regions of every CDS-internal intron, plus the
  flanking exonic bases: the **3 exonic nucleotides before the 5' splice
  site** (`-3` … `-1`) and the **8 intronic nucleotides after it** (donor
  `+1` … `+8`); and the **20 intronic nucleotides before the 3' splice site**
  (acceptor `-20` … `-1`) plus the **3 exonic nucleotides after it** (`+1` …
  `+3`).  Intronic sequence is obtained by mapping the MANE transcript exons
  onto the RefSeqGene (NG_) record.  Intronic positions use `c.N+k` / `c.M-k`
  notation; flanking exonic positions use ordinary `c.` notation.  Each entry
  is `(c.HGVS, g.HGVS)`.

### Protein-level variants

- **`aa_sub(gene, mane="MANE Select")`** → `list[tuple[str, str]]`
  All single amino-acid substitutions.  Each entry is
  `(p.HGVS_1letter, p.HGVS_3letter)`.  The initiator methionine is reported
  as `M1?` / `Met1?`.

## Design notes

### Why no stop-codon (readthrough) mutations?

The CDS annotation includes the terminal stop codon — for example, the `INS`
coding sequence is 333 bp = **110 amino acids + 1 stop codon**.  The variant
generators deliberately iterate only the amino-acid-encoding codons and skip
the terminal stop codon.

Mutating the stop codon is a **stop-loss / readthrough** mutation: translation
continues past the normal stop and appends a C-terminal extension of undefined
length.  This is a distinct variant class from the single-base missense and
nonsense changes enumerated here, so it is intentionally excluded.  To obtain
readthrough variants, enumerate the stop-codon triplet separately.

### Missense vs. synonymous vs. nonsense

- `cds()` reports every single-base change, tagging the protein consequence as
  `p.(X#Y)` (missense / nonsense) or `p.(X#=)` (synonymous).
- `codon_sub()` enumerates all 63 alternative codons at each position —
  silent, missense, and nonsense (stop-gain) included.
- `missense()` returns only true amino-acid changes: synonymous (`=`) and
  nonsense (stop-gain, `*`) substitutions are excluded.

## Validation

The variant generators and genomic-coordinate mapping are verified against five
reference genes via live NCBI Entrez queries.  For every generated variant the
`g.` reference base was checked against the actual chromosome sequence at that
position (plus strand), and strand orientation was confirmed — **~400,000
individual coordinates across TMPRSS6, ADAMTS13, SLC22A5, and CDKN2A, with
zero mismatches**.

| Gene | MANE Select transcript | Chromosome | Strand | Exons |
|---|---|---|---|---|
| INS | NM_000207.3 | NC_000011.10 | − | 3 |
| TMPRSS6 | NM_001374504.1 | NC_000022.11 | − | 18 |
| ADAMTS13 | NM_139027.6 | NC_000009.12 | + | 29 |
| SLC22A5 | NM_003060.4 | NC_000005.10 | + | 10 |
| CDKN2A | NM_000077.5 | NC_000009.12 | − | 3 |

`CDKN2A` additionally exercises both MANE sets — `p16INK4a` (NM_000077.5,
156 aa) via MANE Select and `p14ARF` (NM_058195.4, 132 aa) via MANE Plus
Clinical — confirming that `mane="MANE Select"` / `"MANE Plus Clinical"`
resolve to the correct, distinct transcripts.

## Development

```bash
# Editable install with test dependencies
pip install -e ".[test]"

# Run tests (no network required — 86 tests)
pytest tests/ -v

# Run tests with coverage
pytest --cov=deepmutsim --cov-report=term-missing

# Build a distribution
python -m build
```

## License

MIT — see [LICENSE](LICENSE).
