psimodpy 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.
- psimodpy-0.1.0/.github/copilot-instructions.md +38 -0
- psimodpy-0.1.0/.github/workflows/ci.yml +60 -0
- psimodpy-0.1.0/.github/workflows/release.yml +37 -0
- psimodpy-0.1.0/.gitignore +118 -0
- psimodpy-0.1.0/HISTORY.md +5 -0
- psimodpy-0.1.0/LICENSE +21 -0
- psimodpy-0.1.0/MANIFEST.in +11 -0
- psimodpy-0.1.0/PKG-INFO +150 -0
- psimodpy-0.1.0/README.md +125 -0
- psimodpy-0.1.0/justfile +28 -0
- psimodpy-0.1.0/pyproject.toml +65 -0
- psimodpy-0.1.0/scripts/example.py +209 -0
- psimodpy-0.1.0/src/psimodpy/__init__.py +33 -0
- psimodpy-0.1.0/src/psimodpy/_download.py +30 -0
- psimodpy-0.1.0/src/psimodpy/_formula.py +92 -0
- psimodpy-0.1.0/src/psimodpy/database.py +171 -0
- psimodpy-0.1.0/src/psimodpy/models.py +209 -0
- psimodpy-0.1.0/src/psimodpy/parser.py +250 -0
- psimodpy-0.1.0/src/psimodpy/py.typed +0 -0
- psimodpy-0.1.0/tests/conftest.py +11 -0
- psimodpy-0.1.0/tests/test_basic.py +7 -0
- psimodpy-0.1.0/tests/test_database.py +183 -0
- psimodpy-0.1.0/tests/test_download.py +57 -0
- psimodpy-0.1.0/tests/test_error_handling.py +26 -0
- psimodpy-0.1.0/tests/test_formula.py +138 -0
- psimodpy-0.1.0/tests/test_parser.py +280 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## Copilot Instructions
|
|
2
|
+
|
|
3
|
+
### VERY IMPORTANT INSTRUCTIONS
|
|
4
|
+
|
|
5
|
+
USE THE JUSTFILE WHENEVER POSSIBLE. IF THERE IS NOT A JUSTFILE COMMAND CHECK AGAIN... IF THERE IS STILL NOT A FUCKING JUST COMAND... USE UV PACKAGE MANAGER! THIS IS ALREADY INSTALLED AND AVAILABLE. DO NOT, UNDER ANY CIRCUMSTANCES, INSTALL ANY DEPENDENCIES USING NPM, YARN, PIP, GEM, OR ANY OTHER PACKAGE MANAGER. AND NEVER USE PYHTON / PYTEST DIRECTLY!!! ALWAYS USE JUST FOR AVAILABLE COMMANDS AND ONLY FALL BACK TO UV IF THERE IS NO JUST COMMAND AVAILABLE.
|
|
6
|
+
|
|
7
|
+
### Available Tools
|
|
8
|
+
- Use `just` for all project commands. See `just --list` for available commands.
|
|
9
|
+
- Use `uv` for package management and running scripts. See `uv --help` for usage.
|
|
10
|
+
- Use `git` for version control.
|
|
11
|
+
- Use ty for type checking. `uv run ty check src/ tests/` or `just ty`
|
|
12
|
+
- Use pytest for testing. `uv run pytest tests/` or `just test`
|
|
13
|
+
- use ruff for linting and formatting. `uv run ruff check src/ tests/` or `just lint` and `uv run ruff format src/` or `just format`
|
|
14
|
+
|
|
15
|
+
### Code Style & Philosophy
|
|
16
|
+
|
|
17
|
+
- **Type everything**: Use comprehensive type hints (NDArray, Literal, Protocol, Self, etc.). Generic types should be specific. Use pyhton 3.12 features where applicable. Match-case statements preferred over if-elif chains for discrete values >= 3. Use list, tuple, set over List, Tuple, Set where possible. Dont use Union or Optional, use | operator.
|
|
18
|
+
- **Immutability**: Prefer frozen dataclasses with `slots=True` and functional transformations over mutation. Though this is not absolute.
|
|
19
|
+
- **Explicit over implicit**: Clear, descriptive names. No magic. If there's a performance trade-off, make it obvious.
|
|
20
|
+
- **Simplicity**: Simple, readable code over clever one-liners. Break complex logic into smaller functions.
|
|
21
|
+
|
|
22
|
+
Test do not need to be strongly typed but should still use type hints where reasonable. dont worry about exhaustive typing in tests, nor running ruff/ty on tests.
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
- Concise docstrings - no novels
|
|
27
|
+
- Document the "why" when non-obvious, not the "what"
|
|
28
|
+
- Type hints are documentation - don't repeat them in docstrings. Methods/Function should be able to get by with no/minimal docstrings if types are clear.
|
|
29
|
+
- Use `Raises` section in docstrings for exceptions
|
|
30
|
+
- No placeholder comments like "TODO: implement later" - use `raise NotImplementedError("reason")`
|
|
31
|
+
|
|
32
|
+
### Response Style
|
|
33
|
+
|
|
34
|
+
- Get to the point
|
|
35
|
+
- Show code, minimal explanation
|
|
36
|
+
- If I'm wrong, tell me directly
|
|
37
|
+
- Assume I know Python well - no hand-holding
|
|
38
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
- run: uv sync
|
|
22
|
+
- run: uv run ruff check src
|
|
23
|
+
- run: uv run ruff format --check src
|
|
24
|
+
|
|
25
|
+
type-check:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: astral-sh/setup-uv@v5
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
- run: uv sync
|
|
33
|
+
- run: uv run ty check src
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
strategy:
|
|
38
|
+
matrix:
|
|
39
|
+
python-version: ["3.12", "3.13"]
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- uses: astral-sh/setup-uv@v5
|
|
43
|
+
with:
|
|
44
|
+
enable-cache: true
|
|
45
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
46
|
+
- run: uv sync --python ${{ matrix.python-version }}
|
|
47
|
+
- run: uv run pytest tests
|
|
48
|
+
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: astral-sh/setup-uv@v5
|
|
54
|
+
with:
|
|
55
|
+
enable-cache: true
|
|
56
|
+
- run: uv build
|
|
57
|
+
- uses: actions/upload-artifact@v4
|
|
58
|
+
with:
|
|
59
|
+
name: dist
|
|
60
|
+
path: dist/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
- run: uv build
|
|
21
|
+
- uses: actions/upload-artifact@v4
|
|
22
|
+
with:
|
|
23
|
+
name: dist
|
|
24
|
+
path: dist/
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
needs: build
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment: pypi
|
|
30
|
+
permissions:
|
|
31
|
+
id-token: write
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/download-artifact@v4
|
|
34
|
+
with:
|
|
35
|
+
name: dist
|
|
36
|
+
path: dist/
|
|
37
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Data files (bundled copy lives in src/psimodpy/data/)
|
|
2
|
+
PSI-MOD.obo
|
|
3
|
+
|
|
4
|
+
# Byte-compiled / optimized / DLL files
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
|
|
9
|
+
# C extensions
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
.installed.cfg
|
|
29
|
+
*.egg
|
|
30
|
+
MANIFEST
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
*.manifest
|
|
36
|
+
*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.nox/
|
|
46
|
+
.coverage
|
|
47
|
+
.coverage.*
|
|
48
|
+
.cache
|
|
49
|
+
nosetests.xml
|
|
50
|
+
coverage.xml
|
|
51
|
+
*.cover
|
|
52
|
+
*.py,cover
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
cover/
|
|
56
|
+
|
|
57
|
+
# Translations
|
|
58
|
+
*.mo
|
|
59
|
+
*.pot
|
|
60
|
+
|
|
61
|
+
# Django stuff:
|
|
62
|
+
*.log
|
|
63
|
+
local_settings.py
|
|
64
|
+
db.sqlite3
|
|
65
|
+
db.sqlite3-journal
|
|
66
|
+
|
|
67
|
+
# Flask stuff:
|
|
68
|
+
instance/
|
|
69
|
+
.webassets-cache
|
|
70
|
+
|
|
71
|
+
# Scrapy stuff:
|
|
72
|
+
.scrapy
|
|
73
|
+
|
|
74
|
+
# Sphinx documentation
|
|
75
|
+
docs/_build/
|
|
76
|
+
|
|
77
|
+
# PyBuilder
|
|
78
|
+
target/
|
|
79
|
+
|
|
80
|
+
# Jupyter Notebook
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# IPython
|
|
84
|
+
profile_default/
|
|
85
|
+
ipython_config.py
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
.python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# with no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducible builds.
|
|
100
|
+
# However, if you need to use different versions of dependencies on different environments,
|
|
101
|
+
# you may want to ignore it.
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# uv
|
|
105
|
+
.venv
|
|
106
|
+
uv.lock
|
|
107
|
+
|
|
108
|
+
# ruff
|
|
109
|
+
.ruff_cache/
|
|
110
|
+
|
|
111
|
+
# mypy
|
|
112
|
+
.mypy_cache/
|
|
113
|
+
.dmypy.json
|
|
114
|
+
dmypy.json
|
|
115
|
+
|
|
116
|
+
# editors
|
|
117
|
+
.vscode/
|
|
118
|
+
.idea/
|
psimodpy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Patrick Garrett
|
|
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.
|
psimodpy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: psimodpy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python library for the PSI-MOD protein modification ontology
|
|
5
|
+
Project-URL: Homepage, https://github.com/tacular-omics/psimodpy
|
|
6
|
+
Project-URL: Repository, https://github.com/tacular-omics/psimodpy
|
|
7
|
+
Project-URL: Issues, https://github.com/tacular-omics/psimodpy/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/tacular-omics/psimodpy/blob/main/HISTORY.md
|
|
9
|
+
Author-email: Patrick Garrett <pgarrett@scripps.edu>
|
|
10
|
+
Maintainer-email: Patrick Garrett <pgarrett@scripps.edu>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: PSI-MOD,bioinformatics,mass spectrometry,ontology,protein modification,proteomics
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# psimodpy
|
|
27
|
+
|
|
28
|
+
[](https://github.com/tacular-omics/psimodpy/actions/workflows/ci.yml)
|
|
29
|
+
[](https://pypi.org/project/psimodpy/)
|
|
30
|
+
[](https://pypi.org/project/psimodpy/)
|
|
31
|
+
[](LICENSE)
|
|
32
|
+
|
|
33
|
+
Python library for parsing and querying the [PSI-MOD](https://github.com/HUPO-PSI/psi-mod-CV) protein modification ontology.
|
|
34
|
+
|
|
35
|
+
- Zero dependencies
|
|
36
|
+
- Bundled PSI-MOD data (2,116 entries) — works offline out of the box
|
|
37
|
+
- Typed, immutable data models (`py.typed` / PEP 561)
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install psimodpy
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or with [uv](https://docs.astral.sh/uv/):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv add psimodpy
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Requires Python 3.12+. No third-party dependencies.
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import psimodpy
|
|
57
|
+
|
|
58
|
+
# Load the bundled PSI-MOD database
|
|
59
|
+
db = psimodpy.load()
|
|
60
|
+
|
|
61
|
+
# Lookup by ID
|
|
62
|
+
entry = db[46] # O-phospho-L-serine
|
|
63
|
+
print(entry.name) # "O-phospho-L-serine"
|
|
64
|
+
print(entry.diff_mono) # 79.966331
|
|
65
|
+
print(entry.origin) # AminoAcid.SER
|
|
66
|
+
|
|
67
|
+
# Lookup by name (case-insensitive)
|
|
68
|
+
entry = db.get_by_name("O-phospho-L-serine")
|
|
69
|
+
|
|
70
|
+
# Also accepts MOD:NNNNN format
|
|
71
|
+
entry = db.get_by_id("MOD:00046")
|
|
72
|
+
|
|
73
|
+
# Search across names, definitions, and synonyms
|
|
74
|
+
results = db.search("phospho")
|
|
75
|
+
|
|
76
|
+
# Find all modifications for an amino acid
|
|
77
|
+
ser_mods = db.get_by_origin("S")
|
|
78
|
+
|
|
79
|
+
# Filter entries
|
|
80
|
+
slim = db.filter(slim_only=True, include_obsolete=False)
|
|
81
|
+
|
|
82
|
+
# Formula parsing
|
|
83
|
+
print(entry.dict_diff_formula) # {'C': 0, 'H': 0, 'N': 0, 'O': 3, 'P': 1}
|
|
84
|
+
print(entry.proforma_diff_formula) # 'O3P'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Overview
|
|
88
|
+
|
|
89
|
+
### Loading
|
|
90
|
+
|
|
91
|
+
| Function | Description |
|
|
92
|
+
|----------|-------------|
|
|
93
|
+
| `psimodpy.load()` | Load the bundled PSI-MOD database. |
|
|
94
|
+
| `psimodpy.load_from(path)` | Load from a custom OBO file. |
|
|
95
|
+
| `psimodpy.parse_obo(path)` | Parse an OBO file into a database. |
|
|
96
|
+
| `psimodpy.download_obo()` | Download the latest OBO file from GitHub. |
|
|
97
|
+
|
|
98
|
+
### PsiModDatabase
|
|
99
|
+
|
|
100
|
+
| Method | Description |
|
|
101
|
+
|--------|-------------|
|
|
102
|
+
| `db[id]` | Lookup by ID (int or `"MOD:00046"`), raises `KeyError`. |
|
|
103
|
+
| `db.get_by_id(id)` | Lookup by ID, returns `None` if missing. |
|
|
104
|
+
| `db.get_by_name(name)` | Case-insensitive name lookup. |
|
|
105
|
+
| `db.search(query)` | Full-text search in names, definitions, synonyms. |
|
|
106
|
+
| `db.get_by_origin(aa)` | Find entries by amino acid origin. |
|
|
107
|
+
| `db.get_parents(entry)` | Direct parent entries (is_a hierarchy). |
|
|
108
|
+
| `db.get_children(entry)` | Direct child entries. |
|
|
109
|
+
| `db.get_related(entry, type)` | Follow relationship edges (derives_from, contains, etc.). |
|
|
110
|
+
| `db.filter(...)` | Filter by obsolete/slim status. |
|
|
111
|
+
|
|
112
|
+
### PsiModEntry
|
|
113
|
+
|
|
114
|
+
Each entry provides: `id`, `name`, `definition`, `synonyms`, `is_a`, `relationships`,
|
|
115
|
+
`origin`, `diff_mono`, `diff_avg`, `diff_formula`, `mass_mono`, `mass_avg`, `formula`,
|
|
116
|
+
`term_spec`, `source`, `formal_charge`, `xref_unimod`, `xref_uniprot_ptm`, `xref_gnome`,
|
|
117
|
+
`xref_remap`, `in_slim_subset`, `is_obsolete`.
|
|
118
|
+
|
|
119
|
+
Computed properties: `dict_diff_formula`, `dict_formula`, `proforma_diff_formula`.
|
|
120
|
+
|
|
121
|
+
### Data Types
|
|
122
|
+
|
|
123
|
+
- `AminoAcid` — single-letter amino acid codes
|
|
124
|
+
- `Crosslink` — multi-residue or MOD-referenced origins
|
|
125
|
+
- `Synonym` / `SynonymType` — typed synonyms
|
|
126
|
+
- `Relationship` / `RelationshipType` — directed relationships
|
|
127
|
+
- `TermSpec` — positional specificity
|
|
128
|
+
- `Source` — modification origin
|
|
129
|
+
|
|
130
|
+
## Development
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
just install # install dependencies with uv
|
|
134
|
+
just lint # ruff check
|
|
135
|
+
just format # ruff format
|
|
136
|
+
just ty # ty type check
|
|
137
|
+
just test # pytest
|
|
138
|
+
just check # lint + type check + test
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Related Projects
|
|
142
|
+
|
|
143
|
+
| Package | Description |
|
|
144
|
+
|---------|-------------|
|
|
145
|
+
| [unimodpy](https://github.com/tacular-omics/unimodpy) | Parse and query the UNIMOD mass spectrometry modifications database |
|
|
146
|
+
| [uniprotptmpy](https://github.com/tacular-omics/uniprotptmpy) | Parse and query the UniProt PTM controlled vocabulary |
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
[MIT](LICENSE)
|
psimodpy-0.1.0/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# psimodpy
|
|
2
|
+
|
|
3
|
+
[](https://github.com/tacular-omics/psimodpy/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/psimodpy/)
|
|
5
|
+
[](https://pypi.org/project/psimodpy/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
Python library for parsing and querying the [PSI-MOD](https://github.com/HUPO-PSI/psi-mod-CV) protein modification ontology.
|
|
9
|
+
|
|
10
|
+
- Zero dependencies
|
|
11
|
+
- Bundled PSI-MOD data (2,116 entries) — works offline out of the box
|
|
12
|
+
- Typed, immutable data models (`py.typed` / PEP 561)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install psimodpy
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or with [uv](https://docs.astral.sh/uv/):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv add psimodpy
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requires Python 3.12+. No third-party dependencies.
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import psimodpy
|
|
32
|
+
|
|
33
|
+
# Load the bundled PSI-MOD database
|
|
34
|
+
db = psimodpy.load()
|
|
35
|
+
|
|
36
|
+
# Lookup by ID
|
|
37
|
+
entry = db[46] # O-phospho-L-serine
|
|
38
|
+
print(entry.name) # "O-phospho-L-serine"
|
|
39
|
+
print(entry.diff_mono) # 79.966331
|
|
40
|
+
print(entry.origin) # AminoAcid.SER
|
|
41
|
+
|
|
42
|
+
# Lookup by name (case-insensitive)
|
|
43
|
+
entry = db.get_by_name("O-phospho-L-serine")
|
|
44
|
+
|
|
45
|
+
# Also accepts MOD:NNNNN format
|
|
46
|
+
entry = db.get_by_id("MOD:00046")
|
|
47
|
+
|
|
48
|
+
# Search across names, definitions, and synonyms
|
|
49
|
+
results = db.search("phospho")
|
|
50
|
+
|
|
51
|
+
# Find all modifications for an amino acid
|
|
52
|
+
ser_mods = db.get_by_origin("S")
|
|
53
|
+
|
|
54
|
+
# Filter entries
|
|
55
|
+
slim = db.filter(slim_only=True, include_obsolete=False)
|
|
56
|
+
|
|
57
|
+
# Formula parsing
|
|
58
|
+
print(entry.dict_diff_formula) # {'C': 0, 'H': 0, 'N': 0, 'O': 3, 'P': 1}
|
|
59
|
+
print(entry.proforma_diff_formula) # 'O3P'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## API Overview
|
|
63
|
+
|
|
64
|
+
### Loading
|
|
65
|
+
|
|
66
|
+
| Function | Description |
|
|
67
|
+
|----------|-------------|
|
|
68
|
+
| `psimodpy.load()` | Load the bundled PSI-MOD database. |
|
|
69
|
+
| `psimodpy.load_from(path)` | Load from a custom OBO file. |
|
|
70
|
+
| `psimodpy.parse_obo(path)` | Parse an OBO file into a database. |
|
|
71
|
+
| `psimodpy.download_obo()` | Download the latest OBO file from GitHub. |
|
|
72
|
+
|
|
73
|
+
### PsiModDatabase
|
|
74
|
+
|
|
75
|
+
| Method | Description |
|
|
76
|
+
|--------|-------------|
|
|
77
|
+
| `db[id]` | Lookup by ID (int or `"MOD:00046"`), raises `KeyError`. |
|
|
78
|
+
| `db.get_by_id(id)` | Lookup by ID, returns `None` if missing. |
|
|
79
|
+
| `db.get_by_name(name)` | Case-insensitive name lookup. |
|
|
80
|
+
| `db.search(query)` | Full-text search in names, definitions, synonyms. |
|
|
81
|
+
| `db.get_by_origin(aa)` | Find entries by amino acid origin. |
|
|
82
|
+
| `db.get_parents(entry)` | Direct parent entries (is_a hierarchy). |
|
|
83
|
+
| `db.get_children(entry)` | Direct child entries. |
|
|
84
|
+
| `db.get_related(entry, type)` | Follow relationship edges (derives_from, contains, etc.). |
|
|
85
|
+
| `db.filter(...)` | Filter by obsolete/slim status. |
|
|
86
|
+
|
|
87
|
+
### PsiModEntry
|
|
88
|
+
|
|
89
|
+
Each entry provides: `id`, `name`, `definition`, `synonyms`, `is_a`, `relationships`,
|
|
90
|
+
`origin`, `diff_mono`, `diff_avg`, `diff_formula`, `mass_mono`, `mass_avg`, `formula`,
|
|
91
|
+
`term_spec`, `source`, `formal_charge`, `xref_unimod`, `xref_uniprot_ptm`, `xref_gnome`,
|
|
92
|
+
`xref_remap`, `in_slim_subset`, `is_obsolete`.
|
|
93
|
+
|
|
94
|
+
Computed properties: `dict_diff_formula`, `dict_formula`, `proforma_diff_formula`.
|
|
95
|
+
|
|
96
|
+
### Data Types
|
|
97
|
+
|
|
98
|
+
- `AminoAcid` — single-letter amino acid codes
|
|
99
|
+
- `Crosslink` — multi-residue or MOD-referenced origins
|
|
100
|
+
- `Synonym` / `SynonymType` — typed synonyms
|
|
101
|
+
- `Relationship` / `RelationshipType` — directed relationships
|
|
102
|
+
- `TermSpec` — positional specificity
|
|
103
|
+
- `Source` — modification origin
|
|
104
|
+
|
|
105
|
+
## Development
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
just install # install dependencies with uv
|
|
109
|
+
just lint # ruff check
|
|
110
|
+
just format # ruff format
|
|
111
|
+
just ty # ty type check
|
|
112
|
+
just test # pytest
|
|
113
|
+
just check # lint + type check + test
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Related Projects
|
|
117
|
+
|
|
118
|
+
| Package | Description |
|
|
119
|
+
|---------|-------------|
|
|
120
|
+
| [unimodpy](https://github.com/tacular-omics/unimodpy) | Parse and query the UNIMOD mass spectrometry modifications database |
|
|
121
|
+
| [uniprotptmpy](https://github.com/tacular-omics/uniprotptmpy) | Parse and query the UniProt PTM controlled vocabulary |
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
[MIT](LICENSE)
|
psimodpy-0.1.0/justfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
default: lint format check test
|
|
2
|
+
|
|
3
|
+
# Install dependencies
|
|
4
|
+
install:
|
|
5
|
+
uv sync
|
|
6
|
+
|
|
7
|
+
# Run linting checks
|
|
8
|
+
lint:
|
|
9
|
+
uv run ruff check src
|
|
10
|
+
|
|
11
|
+
# Format code
|
|
12
|
+
format:
|
|
13
|
+
uv run ruff check --select I --fix src
|
|
14
|
+
uv run ruff format src
|
|
15
|
+
|
|
16
|
+
# Run ty type checker
|
|
17
|
+
ty:
|
|
18
|
+
uv run ty check src
|
|
19
|
+
|
|
20
|
+
# Run type checking
|
|
21
|
+
check:
|
|
22
|
+
just lint
|
|
23
|
+
just ty
|
|
24
|
+
just test
|
|
25
|
+
|
|
26
|
+
# Run tests
|
|
27
|
+
test:
|
|
28
|
+
uv run pytest tests
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "psimodpy"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Python library for the PSI-MOD protein modification ontology"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
dependencies = []
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Patrick Garrett", email = "pgarrett@scripps.edu" }
|
|
11
|
+
]
|
|
12
|
+
maintainers = [
|
|
13
|
+
{ name = "Patrick Garrett", email = "pgarrett@scripps.edu" }
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
24
|
+
"Typing :: Typed",
|
|
25
|
+
]
|
|
26
|
+
keywords = ["proteomics", "PSI-MOD", "protein modification", "ontology", "bioinformatics", "mass spectrometry"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/tacular-omics/psimodpy"
|
|
30
|
+
Repository = "https://github.com/tacular-omics/psimodpy"
|
|
31
|
+
Issues = "https://github.com/tacular-omics/psimodpy/issues"
|
|
32
|
+
Changelog = "https://github.com/tacular-omics/psimodpy/blob/main/HISTORY.md"
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["hatchling"]
|
|
36
|
+
build-backend = "hatchling.build"
|
|
37
|
+
|
|
38
|
+
[tool.hatch.build.targets.wheel]
|
|
39
|
+
packages = ["src/psimodpy"]
|
|
40
|
+
|
|
41
|
+
[tool.uv]
|
|
42
|
+
package = true
|
|
43
|
+
dev-dependencies = [
|
|
44
|
+
"pytest>=9.0.2",
|
|
45
|
+
"ruff>=0.14.11",
|
|
46
|
+
"ty>=0.0.11",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
target-version = "py312"
|
|
54
|
+
line-length = 120
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = [
|
|
58
|
+
"E", # pycodestyle errors
|
|
59
|
+
"W", # pycodestyle warnings
|
|
60
|
+
"F", # Pyflakes
|
|
61
|
+
"I", # isort
|
|
62
|
+
"B", # flake8-bugbear
|
|
63
|
+
"UP", # pyupgrade
|
|
64
|
+
]
|
|
65
|
+
|