helmkit 0.2.0__tar.gz → 0.3.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.
- {helmkit-0.2.0 → helmkit-0.3.0}/PKG-INFO +23 -4
- {helmkit-0.2.0 → helmkit-0.3.0}/README.md +22 -3
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/helmkit-benchmark.py +2 -2
- helmkit-0.3.0/benchmarks/helmkit-parallel-benchmark.py +29 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/helmkit-with-reload-benchmark.py +2 -2
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/pypept-benchmark.py +2 -2
- {helmkit-0.2.0 → helmkit-0.3.0}/pyproject.toml +1 -1
- helmkit-0.3.0/src/helmkit/__init__.py +11 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/molecule.py +13 -0
- helmkit-0.3.0/tests/test_parallel_load.py +42 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/uv.lock +1 -1
- helmkit-0.2.0/src/helmkit/__init__.py +0 -5
- {helmkit-0.2.0 → helmkit-0.3.0}/.gitignore +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/.python-version +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/LICENSE +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/README.md +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/data/monomers.sdf +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/data/peptides.csv +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/data/monomers.sdf +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/py.typed +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/cycpeptmpdb.py +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/generate_sdf.py +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/monomers.csv +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/monomers.sdf +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/peptides.csv +0 -0
- {helmkit-0.2.0 → helmkit-0.3.0}/tests/random_peptides.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: helmkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Parse HELM strings into RDKit molecules
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -17,7 +17,7 @@ A Python library for converting HELM (Hierarchical Editing Language for Macromol
|
|
|
17
17
|
from helmkit import Molecule
|
|
18
18
|
|
|
19
19
|
# Create a molecule from a HELM string
|
|
20
|
-
helm_string = "PEPTIDE1{A.R.G}
|
|
20
|
+
helm_string = "PEPTIDE1{A.R.G}$$$$"
|
|
21
21
|
molecule = Molecule(helm_string)
|
|
22
22
|
|
|
23
23
|
# Access the RDKit molecule object
|
|
@@ -31,7 +31,7 @@ from helmkit import Molecule
|
|
|
31
31
|
from rdkit.Chem import AllChem, Draw
|
|
32
32
|
|
|
33
33
|
# Create a simple tripeptide (Ala-Arg-Gly)
|
|
34
|
-
molecule = Molecule("PEPTIDE1{A.R.G}
|
|
34
|
+
molecule = Molecule("PEPTIDE1{A.R.G}$$$$")
|
|
35
35
|
|
|
36
36
|
# Generate 2D coordinates for visualization
|
|
37
37
|
AllChem.Compute2DCoords(molecule.mol)
|
|
@@ -67,7 +67,7 @@ custom_sdf_path = "/path/to/your/custom_monomers.sdf"
|
|
|
67
67
|
custom_monomers = load_monomer_library(custom_sdf_path)
|
|
68
68
|
|
|
69
69
|
# Create molecule with custom monomer data
|
|
70
|
-
molecule = Molecule("PEPTIDE1{A.R.G}
|
|
70
|
+
molecule = Molecule("PEPTIDE1{A.R.G}$$$$", monomer_df=custom_monomers)
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
## SDF File Structure Requirements
|
|
@@ -110,3 +110,22 @@ Ala
|
|
|
110
110
|
|
|
111
111
|
$$$$
|
|
112
112
|
```
|
|
113
|
+
|
|
114
|
+
## Parallel Processing of Peptides
|
|
115
|
+
|
|
116
|
+
For workflows involving a large number of peptides, `helmkit` provides a function to process them in parallel, significantly improving performance.
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from helmkit import load_monomer_library
|
|
120
|
+
from helmkit import load_peptides_in_parallel
|
|
121
|
+
|
|
122
|
+
# Load your custom monomer data (optional)
|
|
123
|
+
custom_sdf_path = "/path/to/your/custom_monomers.sdf"
|
|
124
|
+
monomer_db = load_monomer_library(custom_sdf_path)
|
|
125
|
+
|
|
126
|
+
# A list of HELM strings
|
|
127
|
+
helm_strings = ["PEPTIDE1{A.R.G}$$$$", "PEPTIDE1{S.G.T}$$$$"]
|
|
128
|
+
|
|
129
|
+
# Process peptides in parallel
|
|
130
|
+
molecules = load_peptides_in_parallel(helm_strings, monomer_db)
|
|
131
|
+
```
|
|
@@ -8,7 +8,7 @@ A Python library for converting HELM (Hierarchical Editing Language for Macromol
|
|
|
8
8
|
from helmkit import Molecule
|
|
9
9
|
|
|
10
10
|
# Create a molecule from a HELM string
|
|
11
|
-
helm_string = "PEPTIDE1{A.R.G}
|
|
11
|
+
helm_string = "PEPTIDE1{A.R.G}$$$$"
|
|
12
12
|
molecule = Molecule(helm_string)
|
|
13
13
|
|
|
14
14
|
# Access the RDKit molecule object
|
|
@@ -22,7 +22,7 @@ from helmkit import Molecule
|
|
|
22
22
|
from rdkit.Chem import AllChem, Draw
|
|
23
23
|
|
|
24
24
|
# Create a simple tripeptide (Ala-Arg-Gly)
|
|
25
|
-
molecule = Molecule("PEPTIDE1{A.R.G}
|
|
25
|
+
molecule = Molecule("PEPTIDE1{A.R.G}$$$$")
|
|
26
26
|
|
|
27
27
|
# Generate 2D coordinates for visualization
|
|
28
28
|
AllChem.Compute2DCoords(molecule.mol)
|
|
@@ -58,7 +58,7 @@ custom_sdf_path = "/path/to/your/custom_monomers.sdf"
|
|
|
58
58
|
custom_monomers = load_monomer_library(custom_sdf_path)
|
|
59
59
|
|
|
60
60
|
# Create molecule with custom monomer data
|
|
61
|
-
molecule = Molecule("PEPTIDE1{A.R.G}
|
|
61
|
+
molecule = Molecule("PEPTIDE1{A.R.G}$$$$", monomer_df=custom_monomers)
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
## SDF File Structure Requirements
|
|
@@ -101,3 +101,22 @@ Ala
|
|
|
101
101
|
|
|
102
102
|
$$$$
|
|
103
103
|
```
|
|
104
|
+
|
|
105
|
+
## Parallel Processing of Peptides
|
|
106
|
+
|
|
107
|
+
For workflows involving a large number of peptides, `helmkit` provides a function to process them in parallel, significantly improving performance.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from helmkit import load_monomer_library
|
|
111
|
+
from helmkit import load_peptides_in_parallel
|
|
112
|
+
|
|
113
|
+
# Load your custom monomer data (optional)
|
|
114
|
+
custom_sdf_path = "/path/to/your/custom_monomers.sdf"
|
|
115
|
+
monomer_db = load_monomer_library(custom_sdf_path)
|
|
116
|
+
|
|
117
|
+
# A list of HELM strings
|
|
118
|
+
helm_strings = ["PEPTIDE1{A.R.G}$$$$", "PEPTIDE1{S.G.T}$$$$"]
|
|
119
|
+
|
|
120
|
+
# Process peptides in parallel
|
|
121
|
+
molecules = load_peptides_in_parallel(helm_strings, monomer_db)
|
|
122
|
+
```
|
|
@@ -14,12 +14,12 @@ def main():
|
|
|
14
14
|
# (as these do not work with pyPept)
|
|
15
15
|
regex = r"\[[^\]]*[\(\s-][^\]]*\]"
|
|
16
16
|
df = df.filter(pl.col("HELM").str.contains(regex).not_())
|
|
17
|
+
helms = df["HELM"].to_list()
|
|
17
18
|
|
|
18
19
|
monomer_db = load_monomer_library(data_dir / "monomers.sdf")
|
|
19
20
|
|
|
20
21
|
start = time.perf_counter()
|
|
21
|
-
for
|
|
22
|
-
helm = row["HELM"]
|
|
22
|
+
for helm in helms:
|
|
23
23
|
Molecule(helm, monomer_db)
|
|
24
24
|
end = time.perf_counter()
|
|
25
25
|
print(f"Processed {df.height} peptides in {end - start:.2f} seconds")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import polars as pl
|
|
5
|
+
from helmkit import load_monomer_library
|
|
6
|
+
from helmkit import load_peptides_in_parallel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
data_dir = Path(__file__).parent / "data"
|
|
11
|
+
df = pl.read_csv(data_dir / "peptides.csv")
|
|
12
|
+
|
|
13
|
+
# Remove peptides with monomers containing parentheses, spaces or hyphens
|
|
14
|
+
# (as these do not work with pyPept)
|
|
15
|
+
regex = r"\[[^\]]*[\(\s-][^\]]*\]"
|
|
16
|
+
df = df.filter(pl.col("HELM").str.contains(regex).not_())
|
|
17
|
+
helms = df["HELM"].to_list()
|
|
18
|
+
|
|
19
|
+
monomer_db = load_monomer_library(data_dir / "monomers.sdf")
|
|
20
|
+
|
|
21
|
+
start = time.perf_counter()
|
|
22
|
+
load_peptides_in_parallel(helms, monomer_db)
|
|
23
|
+
end = time.perf_counter()
|
|
24
|
+
print(f"Processed {df.height} peptides in {end - start:.2f} seconds")
|
|
25
|
+
print(f"Average time per peptide: {(end - start) / df.height:.6f} seconds")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if __name__ == "__main__":
|
|
29
|
+
main()
|
|
@@ -14,10 +14,10 @@ def main():
|
|
|
14
14
|
# (as these do not work with pyPept)
|
|
15
15
|
regex = r"\[[^\]]*[\(\s-][^\]]*\]"
|
|
16
16
|
df = df.filter(pl.col("HELM").str.contains(regex).not_())
|
|
17
|
+
helms = df["HELM"].to_list()
|
|
17
18
|
|
|
18
19
|
start = time.perf_counter()
|
|
19
|
-
for
|
|
20
|
-
helm = row["HELM"]
|
|
20
|
+
for helm in helms:
|
|
21
21
|
monomer_db = load_monomer_library(data_dir / "monomers.sdf")
|
|
22
22
|
Molecule(helm, monomer_db)
|
|
23
23
|
end = time.perf_counter()
|
|
@@ -15,13 +15,13 @@ def main():
|
|
|
15
15
|
# (as these do not work with pyPept)
|
|
16
16
|
regex = r"\[[^\]]*[\(\s-][^\]]*\]"
|
|
17
17
|
df = df.filter(pl.col("HELM").str.contains(regex).not_())
|
|
18
|
+
helms = df["HELM"].to_list()
|
|
18
19
|
|
|
19
20
|
monomer_lib_dir = str(data_dir.relative_to(Path.cwd()))
|
|
20
21
|
monomer_lib = "monomers.sdf"
|
|
21
22
|
|
|
22
23
|
start = time.perf_counter()
|
|
23
|
-
for
|
|
24
|
-
helm = row["HELM"]
|
|
24
|
+
for helm in helms:
|
|
25
25
|
converter = Converter(helm=helm)
|
|
26
26
|
sequence = Sequence(converter.get_biln(), monomer_lib_dir, monomer_lib)
|
|
27
27
|
Molecule(sequence)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .molecule import load_monomer_library
|
|
2
|
+
from .molecule import load_peptides_in_parallel
|
|
3
|
+
from .molecule import Molecule
|
|
4
|
+
from .molecule import SequenceConstants
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"load_monomer_library",
|
|
8
|
+
"load_peptides_in_parallel",
|
|
9
|
+
"Molecule",
|
|
10
|
+
"SequenceConstants",
|
|
11
|
+
]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import copy
|
|
2
|
+
import multiprocessing
|
|
2
3
|
import re
|
|
3
4
|
import warnings
|
|
4
5
|
from functools import lru_cache
|
|
@@ -456,3 +457,15 @@ class Molecule:
|
|
|
456
457
|
"""Clean up the molecule by removing dummy atoms and sanitizing."""
|
|
457
458
|
self.mol = Chem.DeleteSubstructs(self.mol, Chem.MolFromSmarts("[#0]"))
|
|
458
459
|
Chem.SanitizeMol(self.mol)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def _load_peptide(helm: str, monomer_df: Optional[Dict] = None) -> Molecule:
|
|
463
|
+
return Molecule(helm, monomer_df)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def load_peptides_in_parallel(
|
|
467
|
+
helms: List[str], monomer_df: Optional[Dict] = None
|
|
468
|
+
) -> List[Molecule]:
|
|
469
|
+
args = [(helm, monomer_df) for helm in helms]
|
|
470
|
+
with multiprocessing.Pool() as pool:
|
|
471
|
+
return pool.starmap(_load_peptide, args)
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|