helmkit 0.3.0__tar.gz → 0.3.1__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.
- helmkit-0.3.1/.github/workflows/main.yml +22 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/PKG-INFO +52 -1
- {helmkit-0.3.0 → helmkit-0.3.1}/README.md +51 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/README.md +10 -7
- {helmkit-0.3.0 → helmkit-0.3.1}/pyproject.toml +2 -1
- {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/molecule.py +8 -5
- helmkit-0.3.1/tests/backup +66 -0
- helmkit-0.3.1/tests/test_cycpeptmpdb.py +29 -0
- helmkit-0.3.1/tests/test_parallel_load.py +28 -0
- helmkit-0.3.0/tests/random_peptides.py → helmkit-0.3.1/tests/test_random_peptides.py +3 -4
- {helmkit-0.3.0 → helmkit-0.3.1}/uv.lock +54 -0
- helmkit-0.3.0/tests/cycpeptmpdb.py +0 -43
- helmkit-0.3.0/tests/test_parallel_load.py +0 -42
- {helmkit-0.3.0 → helmkit-0.3.1}/.gitignore +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/.python-version +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/LICENSE +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/data/monomers.sdf +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/data/peptides.csv +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-benchmark.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-parallel-benchmark.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-with-reload-benchmark.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/pypept-benchmark.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/__init__.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/data/monomers.sdf +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/py.typed +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/generate_sdf.py +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/monomers.csv +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/monomers.sdf +0 -0
- {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/peptides.csv +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Run tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- '**/*.py'
|
|
7
|
+
pull_request:
|
|
8
|
+
paths:
|
|
9
|
+
- '**/*.py'
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Set up uv
|
|
18
|
+
uses: astral-sh/setup-uv@v6
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: uv sync -U
|
|
21
|
+
- name: Test with pytest
|
|
22
|
+
run: uv run pytest
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: helmkit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Parse HELM strings into RDKit molecules
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -11,6 +11,18 @@ Description-Content-Type: text/markdown
|
|
|
11
11
|
|
|
12
12
|
A Python library for converting HELM (Hierarchical Editing Language for Macromolecules) notation to RDKit molecules.
|
|
13
13
|
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Basic Usage](#basic-usage)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick Example](#quick-example)
|
|
19
|
+
- [Understanding HELM Notation](#understanding-helm-notation)
|
|
20
|
+
- [Using Custom Monomer Data](#using-custom-monomer-data)
|
|
21
|
+
- [SDF File Structure Requirements](#sdf-file-structure-requirements)
|
|
22
|
+
- [Parallel Processing of Peptides](#parallel-processing-of-peptides)
|
|
23
|
+
- [Development Setup](#development-setup)
|
|
24
|
+
- [Running Tests](#running-tests)
|
|
25
|
+
|
|
14
26
|
## Basic Usage
|
|
15
27
|
|
|
16
28
|
```python
|
|
@@ -24,6 +36,28 @@ molecule = Molecule(helm_string)
|
|
|
24
36
|
rdkit_mol = molecule.mol
|
|
25
37
|
```
|
|
26
38
|
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
To install `helmkit`, you can use either [`uv`](https://github.com/astral-sh/uv) or `pip`.
|
|
42
|
+
|
|
43
|
+
### With [`uv`](https://github.com/astral-sh/uv)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv pip install helmkit
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
or if you have added it as a dependency to your `pyproject.toml`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv add helmkit
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Without `uv`
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install helmkit
|
|
59
|
+
```
|
|
60
|
+
|
|
27
61
|
## Quick Example
|
|
28
62
|
|
|
29
63
|
```python
|
|
@@ -129,3 +163,20 @@ helm_strings = ["PEPTIDE1{A.R.G}$$$$", "PEPTIDE1{S.G.T}$$$$"]
|
|
|
129
163
|
# Process peptides in parallel
|
|
130
164
|
molecules = load_peptides_in_parallel(helm_strings, monomer_db)
|
|
131
165
|
```
|
|
166
|
+
|
|
167
|
+
## Development Setup
|
|
168
|
+
|
|
169
|
+
To set up a development environment, first clone the repository.
|
|
170
|
+
Then, from the root of the repository, use `uv` to sync the environment:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
uv sync -U
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Running Tests
|
|
177
|
+
|
|
178
|
+
To run the test suite, execute `pytest` from the root of the repository:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
pytest
|
|
182
|
+
```
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
A Python library for converting HELM (Hierarchical Editing Language for Macromolecules) notation to RDKit molecules.
|
|
4
4
|
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Basic Usage](#basic-usage)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Quick Example](#quick-example)
|
|
10
|
+
- [Understanding HELM Notation](#understanding-helm-notation)
|
|
11
|
+
- [Using Custom Monomer Data](#using-custom-monomer-data)
|
|
12
|
+
- [SDF File Structure Requirements](#sdf-file-structure-requirements)
|
|
13
|
+
- [Parallel Processing of Peptides](#parallel-processing-of-peptides)
|
|
14
|
+
- [Development Setup](#development-setup)
|
|
15
|
+
- [Running Tests](#running-tests)
|
|
16
|
+
|
|
5
17
|
## Basic Usage
|
|
6
18
|
|
|
7
19
|
```python
|
|
@@ -15,6 +27,28 @@ molecule = Molecule(helm_string)
|
|
|
15
27
|
rdkit_mol = molecule.mol
|
|
16
28
|
```
|
|
17
29
|
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
To install `helmkit`, you can use either [`uv`](https://github.com/astral-sh/uv) or `pip`.
|
|
33
|
+
|
|
34
|
+
### With [`uv`](https://github.com/astral-sh/uv)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv pip install helmkit
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
or if you have added it as a dependency to your `pyproject.toml`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv add helmkit
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Without `uv`
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install helmkit
|
|
50
|
+
```
|
|
51
|
+
|
|
18
52
|
## Quick Example
|
|
19
53
|
|
|
20
54
|
```python
|
|
@@ -120,3 +154,20 @@ helm_strings = ["PEPTIDE1{A.R.G}$$$$", "PEPTIDE1{S.G.T}$$$$"]
|
|
|
120
154
|
# Process peptides in parallel
|
|
121
155
|
molecules = load_peptides_in_parallel(helm_strings, monomer_db)
|
|
122
156
|
```
|
|
157
|
+
|
|
158
|
+
## Development Setup
|
|
159
|
+
|
|
160
|
+
To set up a development environment, first clone the repository.
|
|
161
|
+
Then, from the root of the repository, use `uv` to sync the environment:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
uv sync -U
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Running Tests
|
|
168
|
+
|
|
169
|
+
To run the test suite, execute `pytest` from the root of the repository:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pytest
|
|
173
|
+
```
|
|
@@ -33,15 +33,18 @@ that `pyPept` cannot handle were excluded (monomers with names containing whites
|
|
|
33
33
|
hyphens or parenthesis), resulting in a total of 4694 peptides. We measured the total
|
|
34
34
|
and average parsing time:
|
|
35
35
|
|
|
36
|
-
| Tool | Total Time (s) | Avg Time per Peptide (s) |
|
|
37
|
-
|
|
38
|
-
| `pyPept` |
|
|
39
|
-
| `helmkit`
|
|
40
|
-
| `helmkit`
|
|
36
|
+
| Tool | Total Time (s) | Avg Time per Peptide (s) | Peptides per Second |
|
|
37
|
+
|-------------------------------------|---------------:|-------------------------:|--------------------:|
|
|
38
|
+
| `pyPept` | 676.65 | 0.14400 | 6.94 |
|
|
39
|
+
| `helmkit` (DB reload every peptide) | 261.81 | 0.05600 | 17.93 |
|
|
40
|
+
| `helmkit` | 3.60 | 0.00077 | 1303.89 |
|
|
41
|
+
| `helmkit` (parallel loading) | 1.42 | 0.00030 | 3305.63 |
|
|
41
42
|
|
|
42
43
|
`helmkit` outperforms `pyPept` by approximately 188× when loading the monomer library
|
|
43
44
|
once per session. When forced to reload the library for every peptide (needs disabling
|
|
44
|
-
memoization in the source code), `helmkit` is still about 3× faster.
|
|
45
|
+
memoization in the source code), `helmkit` is still about 3× faster. If we use
|
|
46
|
+
parallelized loading in `helmkit`, we achieve an additional 2.5× speedup, resulting in a
|
|
47
|
+
total speedup of approximately 477× over `pyPept`.
|
|
45
48
|
|
|
46
49
|
## Environment
|
|
47
50
|
|
|
@@ -52,4 +55,4 @@ versions:
|
|
|
52
55
|
- `polars 1.31.0` (CSV parsing and dataframe processing)
|
|
53
56
|
- `rdkit 2025.3.3` (target output format and structure processing)
|
|
54
57
|
- `pypept 1.0.0` (commit `ade9f5840691ad1f8fa22d13939a665c25175d5a`)
|
|
55
|
-
- `helmkit 0.
|
|
58
|
+
- `helmkit 0.3.0` (local development version)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "helmkit"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.1"
|
|
4
4
|
description = "Parse HELM strings into RDKit molecules"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -16,6 +16,7 @@ build-backend = "hatchling.build"
|
|
|
16
16
|
dev = [
|
|
17
17
|
"polars>=1.31.0",
|
|
18
18
|
"pypept",
|
|
19
|
+
"pytest>=8.4.1",
|
|
19
20
|
"pyupgrade>=3.20.0",
|
|
20
21
|
"reorder-python-imports>=3.15.0",
|
|
21
22
|
"tqdm>=4.67.1",
|
|
@@ -69,8 +69,14 @@ def infer_attachment_points(molecule: Chem.Mol, rgroup_indices: List[int]) -> Li
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
@lru_cache
|
|
72
|
-
def load_monomer_library(library_path: str) -> Dict:
|
|
72
|
+
def load_monomer_library(library_path: Optional[str] = None) -> Dict:
|
|
73
73
|
"""Load and prepare monomer data from SDF file."""
|
|
74
|
+
if library_path is None:
|
|
75
|
+
library_path = str(
|
|
76
|
+
files(SequenceConstants.def_path).joinpath(
|
|
77
|
+
SequenceConstants.def_lib_filename
|
|
78
|
+
)
|
|
79
|
+
)
|
|
74
80
|
monomers_dict = {}
|
|
75
81
|
supplier = Chem.SDMolSupplier(library_path)
|
|
76
82
|
|
|
@@ -112,10 +118,7 @@ class Molecule:
|
|
|
112
118
|
self.chain_offset = {}
|
|
113
119
|
|
|
114
120
|
if monomer_df is None:
|
|
115
|
-
|
|
116
|
-
SequenceConstants.def_lib_filename
|
|
117
|
-
)
|
|
118
|
-
self.monomer_df = load_monomer_library(str(default_monomer_df_filepath))
|
|
121
|
+
self.monomer_df = load_monomer_library()
|
|
119
122
|
else:
|
|
120
123
|
self.monomer_df = monomer_df
|
|
121
124
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from rdkit import Chem
|
|
4
|
+
from helmkit.molecule import (
|
|
5
|
+
Molecule,
|
|
6
|
+
load_monomer_library,
|
|
7
|
+
load_peptides_in_parallel,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture(scope="module")
|
|
12
|
+
def monomer_library():
|
|
13
|
+
"""Fixture to load the monomer library for testing."""
|
|
14
|
+
path = Path(__file__).parent / "data" / "monomers.sdf"
|
|
15
|
+
return load_monomer_library(path)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_load_monomer_library(monomer_library):
|
|
19
|
+
"""Test loading the monomer library."""
|
|
20
|
+
assert "A" in monomer_library
|
|
21
|
+
assert "G" in monomer_library
|
|
22
|
+
assert "T" in monomer_library
|
|
23
|
+
assert monomer_library["A"]["m_type"] == "aa"
|
|
24
|
+
assert monomer_library["A"]["m_romol"].GetNumAtoms() > 0
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_simple_peptide(monomer_library):
|
|
28
|
+
"""Test creating a simple peptide from a HELM string."""
|
|
29
|
+
helm = "PEPTIDE1{A.G.T}$$$$"
|
|
30
|
+
mol = Molecule(helm, monomer_df=monomer_library)
|
|
31
|
+
assert isinstance(mol.mol, Chem.Mol)
|
|
32
|
+
# Number of atoms will vary based on monomer definitions, but it should be > 0
|
|
33
|
+
assert mol.mol.GetNumAtoms() > 0
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_peptide_with_connection(monomer_library):
|
|
37
|
+
"""Test a peptide with a connection."""
|
|
38
|
+
helm = "PEPTIDE1{A.G.G}$PEPTIDE1,PEPTIDE1,1:R3-3:R1$$$"
|
|
39
|
+
mol = Molecule(helm, monomer_df=monomer_library)
|
|
40
|
+
assert isinstance(mol.mol, Chem.Mol)
|
|
41
|
+
assert mol.mol.GetNumAtoms() > 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_invalid_monomer(monomer_library):
|
|
45
|
+
"""Test HELM string with an invalid monomer."""
|
|
46
|
+
helm = "PEPTIDE1{X.Y.Z}$$$$"
|
|
47
|
+
with pytest.raises(ValueError, match="Monomer X not found in monomer library"):
|
|
48
|
+
Molecule(helm, monomer_df=monomer_library)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_invalid_helm_string(monomer_library):
|
|
52
|
+
"""Test an invalid HELM string."""
|
|
53
|
+
helm = "PEPTIDE1{A.G.T}"
|
|
54
|
+
mol = Molecule(helm, monomer_df=monomer_library)
|
|
55
|
+
assert len(mol.monomers) == 3
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_load_peptides_in_parallel(monomer_library):
|
|
59
|
+
"""Test loading peptides in parallel."""
|
|
60
|
+
helms = ["PEPTIDE1{A.G.T}$$$$", "PEPTIDE1{G.A}$$$$"]
|
|
61
|
+
molecules = load_peptides_in_parallel(helms, monomer_df=monomer_library)
|
|
62
|
+
assert len(molecules) == 2
|
|
63
|
+
assert isinstance(molecules[0].mol, Chem.Mol)
|
|
64
|
+
assert isinstance(molecules[1].mol, Chem.Mol)
|
|
65
|
+
assert molecules[0].mol.GetNumAtoms() > 0
|
|
66
|
+
assert molecules[1].mol.GetNumAtoms() > 0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import polars as pl
|
|
4
|
+
from helmkit import load_monomer_library
|
|
5
|
+
from helmkit import Molecule
|
|
6
|
+
from rdkit import Chem
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test():
|
|
11
|
+
data_dir = Path(__file__).parent / "data"
|
|
12
|
+
df = pl.read_csv(data_dir / "peptides.csv")
|
|
13
|
+
monomer_db = load_monomer_library(data_dir / "monomers.sdf")
|
|
14
|
+
for row in tqdm(df.iter_rows(named=True), total=df.height):
|
|
15
|
+
helm = row["HELM"]
|
|
16
|
+
smiles = row["SMILES"]
|
|
17
|
+
try:
|
|
18
|
+
m = Molecule(helm, monomer_db)
|
|
19
|
+
except:
|
|
20
|
+
print(row)
|
|
21
|
+
raise
|
|
22
|
+
inchi1 = Chem.MolToInchi(m.mol)
|
|
23
|
+
other = Chem.MolFromSmiles(smiles)
|
|
24
|
+
inchi2 = Chem.MolToInchi(other)
|
|
25
|
+
assert inchi1 == inchi2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if __name__ == "__main__":
|
|
29
|
+
test()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import polars as pl
|
|
4
|
+
from helmkit import load_monomer_library
|
|
5
|
+
from helmkit import load_peptides_in_parallel
|
|
6
|
+
from rdkit import Chem
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test():
|
|
11
|
+
data_dir = Path(__file__).parent / "data"
|
|
12
|
+
df = pl.read_csv(data_dir / "peptides.csv")
|
|
13
|
+
monomer_db = load_monomer_library(str(data_dir / "monomers.sdf"))
|
|
14
|
+
helms = df["HELM"].to_list()
|
|
15
|
+
|
|
16
|
+
molecules_parallel = load_peptides_in_parallel(helms, monomer_db)
|
|
17
|
+
for m, row in tqdm(
|
|
18
|
+
zip(molecules_parallel, df.iter_rows(named=True)), total=df.height
|
|
19
|
+
):
|
|
20
|
+
smiles = row["SMILES"]
|
|
21
|
+
inchi1 = Chem.MolToInchi(m.mol)
|
|
22
|
+
other = Chem.MolFromSmiles(smiles)
|
|
23
|
+
inchi2 = Chem.MolToInchi(other)
|
|
24
|
+
assert inchi1 == inchi2
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
test()
|
|
@@ -5,7 +5,7 @@ from rdkit import Chem
|
|
|
5
5
|
from tqdm import tqdm
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def test():
|
|
9
9
|
random.seed(0)
|
|
10
10
|
aminoacids = "ACDEFGHIKLMNPQRSTVWY"
|
|
11
11
|
for _ in tqdm(range(1000)):
|
|
@@ -15,9 +15,8 @@ def main():
|
|
|
15
15
|
molecule = Molecule(helm)
|
|
16
16
|
inchi1 = Chem.MolToInchi(molecule.mol)
|
|
17
17
|
inchi2 = Chem.MolToInchi(Chem.MolFromSequence(peptide))
|
|
18
|
-
|
|
19
|
-
raise ValueError(f"{inchi1} != {inchi2}")
|
|
18
|
+
assert inchi1 == inchi2
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
if __name__ == "__main__":
|
|
23
|
-
|
|
22
|
+
test()
|
|
@@ -123,6 +123,7 @@ dependencies = [
|
|
|
123
123
|
dev = [
|
|
124
124
|
{ name = "polars" },
|
|
125
125
|
{ name = "pypept" },
|
|
126
|
+
{ name = "pytest" },
|
|
126
127
|
{ name = "pyupgrade" },
|
|
127
128
|
{ name = "reorder-python-imports" },
|
|
128
129
|
{ name = "tqdm" },
|
|
@@ -135,6 +136,7 @@ requires-dist = [{ name = "rdkit", specifier = ">=2025.3.3" }]
|
|
|
135
136
|
dev = [
|
|
136
137
|
{ name = "polars", specifier = ">=1.31.0" },
|
|
137
138
|
{ name = "pypept", git = "https://github.com/Boehringer-Ingelheim/pyPept.git" },
|
|
139
|
+
{ name = "pytest", specifier = ">=8.4.1" },
|
|
138
140
|
{ name = "pyupgrade", specifier = ">=3.20.0" },
|
|
139
141
|
{ name = "reorder-python-imports", specifier = ">=3.15.0" },
|
|
140
142
|
{ name = "tqdm", specifier = ">=4.67.1" },
|
|
@@ -177,6 +179,15 @@ wheels = [
|
|
|
177
179
|
{ url = "https://files.pythonhosted.org/packages/d7/91/c1b597004248bd7ce6c9593465308a1a5f0467c4ec4056aa51a6c017a669/igraph-0.11.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f35694100691bf8ef0c370615d87bcf1d6c0f15e356269c6357f8f78a9f1acea", size = 2926242, upload-time = "2025-06-11T09:27:18.553Z" },
|
|
178
180
|
]
|
|
179
181
|
|
|
182
|
+
[[package]]
|
|
183
|
+
name = "iniconfig"
|
|
184
|
+
version = "2.1.0"
|
|
185
|
+
source = { registry = "https://pypi.org/simple" }
|
|
186
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
|
|
187
|
+
wheels = [
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
|
|
189
|
+
]
|
|
190
|
+
|
|
180
191
|
[[package]]
|
|
181
192
|
name = "numpy"
|
|
182
193
|
version = "2.3.1"
|
|
@@ -235,6 +246,15 @@ wheels = [
|
|
|
235
246
|
{ url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" },
|
|
236
247
|
]
|
|
237
248
|
|
|
249
|
+
[[package]]
|
|
250
|
+
name = "packaging"
|
|
251
|
+
version = "25.0"
|
|
252
|
+
source = { registry = "https://pypi.org/simple" }
|
|
253
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
|
|
254
|
+
wheels = [
|
|
255
|
+
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
|
256
|
+
]
|
|
257
|
+
|
|
238
258
|
[[package]]
|
|
239
259
|
name = "pandas"
|
|
240
260
|
version = "2.3.1"
|
|
@@ -360,6 +380,15 @@ wheels = [
|
|
|
360
380
|
{ url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" },
|
|
361
381
|
]
|
|
362
382
|
|
|
383
|
+
[[package]]
|
|
384
|
+
name = "pluggy"
|
|
385
|
+
version = "1.6.0"
|
|
386
|
+
source = { registry = "https://pypi.org/simple" }
|
|
387
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
388
|
+
wheels = [
|
|
389
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
390
|
+
]
|
|
391
|
+
|
|
363
392
|
[[package]]
|
|
364
393
|
name = "polars"
|
|
365
394
|
version = "1.31.0"
|
|
@@ -374,6 +403,15 @@ wheels = [
|
|
|
374
403
|
{ url = "https://files.pythonhosted.org/packages/40/4b/0673a68ac4d6527fac951970e929c3b4440c654f994f0c957bd5556deb38/polars-1.31.0-cp39-abi3-win_arm64.whl", hash = "sha256:62ef23bb9d10dca4c2b945979f9a50812ac4ace4ed9e158a6b5d32a7322e6f75", size = 31469078, upload-time = "2025-06-18T11:59:59.242Z" },
|
|
375
404
|
]
|
|
376
405
|
|
|
406
|
+
[[package]]
|
|
407
|
+
name = "pygments"
|
|
408
|
+
version = "2.19.2"
|
|
409
|
+
source = { registry = "https://pypi.org/simple" }
|
|
410
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
|
411
|
+
wheels = [
|
|
412
|
+
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
|
413
|
+
]
|
|
414
|
+
|
|
377
415
|
[[package]]
|
|
378
416
|
name = "pypept"
|
|
379
417
|
version = "1.0.0"
|
|
@@ -387,6 +425,22 @@ dependencies = [
|
|
|
387
425
|
{ name = "requests" },
|
|
388
426
|
]
|
|
389
427
|
|
|
428
|
+
[[package]]
|
|
429
|
+
name = "pytest"
|
|
430
|
+
version = "8.4.1"
|
|
431
|
+
source = { registry = "https://pypi.org/simple" }
|
|
432
|
+
dependencies = [
|
|
433
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
434
|
+
{ name = "iniconfig" },
|
|
435
|
+
{ name = "packaging" },
|
|
436
|
+
{ name = "pluggy" },
|
|
437
|
+
{ name = "pygments" },
|
|
438
|
+
]
|
|
439
|
+
sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" }
|
|
440
|
+
wheels = [
|
|
441
|
+
{ url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" },
|
|
442
|
+
]
|
|
443
|
+
|
|
390
444
|
[[package]]
|
|
391
445
|
name = "python-dateutil"
|
|
392
446
|
version = "2.9.0.post0"
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
import polars as pl
|
|
4
|
-
from helmkit import load_monomer_library
|
|
5
|
-
from helmkit import Molecule
|
|
6
|
-
from rdkit import Chem
|
|
7
|
-
from rdkit.Chem import AllChem
|
|
8
|
-
from rdkit.Chem import Draw
|
|
9
|
-
from tqdm import tqdm
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def main():
|
|
13
|
-
data_dir = Path(__file__).parent / "data"
|
|
14
|
-
df = pl.read_csv(data_dir / "peptides.csv")
|
|
15
|
-
monomer_db = load_monomer_library(data_dir / "monomers.sdf")
|
|
16
|
-
for row in tqdm(df.iter_rows(named=True), total=df.height):
|
|
17
|
-
helm = row["HELM"]
|
|
18
|
-
smiles = row["SMILES"]
|
|
19
|
-
try:
|
|
20
|
-
m = Molecule(helm, monomer_db)
|
|
21
|
-
except:
|
|
22
|
-
print(row)
|
|
23
|
-
raise
|
|
24
|
-
inchi1 = Chem.MolToInchi(m.mol)
|
|
25
|
-
other = Chem.MolFromSmiles(smiles)
|
|
26
|
-
inchi2 = Chem.MolToInchi(other)
|
|
27
|
-
if inchi1 != inchi2:
|
|
28
|
-
mistmatches_dir = Path(__file__).parent / "mismatches"
|
|
29
|
-
mistmatches_dir.mkdir(exist_ok=True)
|
|
30
|
-
AllChem.Compute2DCoords(m.mol, clearConfs=True)
|
|
31
|
-
Chem.AssignAtomChiralTagsFromStructure(m.mol)
|
|
32
|
-
AllChem.Compute2DCoords(other, clearConfs=True)
|
|
33
|
-
Chem.AssignAtomChiralTagsFromStructure(other)
|
|
34
|
-
# Draw the two molecules to an image
|
|
35
|
-
img = Draw.MolsToGridImage(
|
|
36
|
-
[m.mol, other], molsPerRow=2, subImgSize=(800, 800)
|
|
37
|
-
)
|
|
38
|
-
img.save(mistmatches_dir / f"{row['ID']}.png")
|
|
39
|
-
raise ValueError(f"{inchi1} != {inchi2} for row {row}")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if __name__ == "__main__":
|
|
43
|
-
main()
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
import polars as pl
|
|
4
|
-
from helmkit import load_monomer_library
|
|
5
|
-
from helmkit import load_peptides_in_parallel
|
|
6
|
-
from rdkit import Chem
|
|
7
|
-
from rdkit.Chem import AllChem
|
|
8
|
-
from rdkit.Chem import Draw
|
|
9
|
-
from tqdm import tqdm
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def main():
|
|
13
|
-
data_dir = Path(__file__).parent / "data"
|
|
14
|
-
df = pl.read_csv(data_dir / "peptides.csv")
|
|
15
|
-
monomer_db = load_monomer_library(str(data_dir / "monomers.sdf"))
|
|
16
|
-
helms = df["HELM"].to_list()
|
|
17
|
-
|
|
18
|
-
molecules_parallel = load_peptides_in_parallel(helms, monomer_db)
|
|
19
|
-
for m, row in tqdm(
|
|
20
|
-
zip(molecules_parallel, df.iter_rows(named=True)), total=df.height
|
|
21
|
-
):
|
|
22
|
-
smiles = row["SMILES"]
|
|
23
|
-
inchi1 = Chem.MolToInchi(m.mol)
|
|
24
|
-
other = Chem.MolFromSmiles(smiles)
|
|
25
|
-
inchi2 = Chem.MolToInchi(other)
|
|
26
|
-
if inchi1 != inchi2:
|
|
27
|
-
mistmatches_dir = Path(__file__).parent / "mismatches"
|
|
28
|
-
mistmatches_dir.mkdir(exist_ok=True)
|
|
29
|
-
AllChem.Compute2DCoords(m.mol, clearConfs=True)
|
|
30
|
-
Chem.AssignAtomChiralTagsFromStructure(m.mol)
|
|
31
|
-
AllChem.Compute2DCoords(other, clearConfs=True)
|
|
32
|
-
Chem.AssignAtomChiralTagsFromStructure(other)
|
|
33
|
-
# Draw the two molecules to an image
|
|
34
|
-
img = Draw.MolsToGridImage(
|
|
35
|
-
[m.mol, other], molsPerRow=2, subImgSize=(800, 800)
|
|
36
|
-
)
|
|
37
|
-
img.save(mistmatches_dir / f"{row['ID']}.png")
|
|
38
|
-
raise ValueError(f"{inchi1} != {inchi2} for row {row}")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if __name__ == "__main__":
|
|
42
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|