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.
Files changed (26) hide show
  1. {helmkit-0.2.0 → helmkit-0.3.0}/PKG-INFO +23 -4
  2. {helmkit-0.2.0 → helmkit-0.3.0}/README.md +22 -3
  3. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/helmkit-benchmark.py +2 -2
  4. helmkit-0.3.0/benchmarks/helmkit-parallel-benchmark.py +29 -0
  5. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/helmkit-with-reload-benchmark.py +2 -2
  6. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/pypept-benchmark.py +2 -2
  7. {helmkit-0.2.0 → helmkit-0.3.0}/pyproject.toml +1 -1
  8. helmkit-0.3.0/src/helmkit/__init__.py +11 -0
  9. {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/molecule.py +13 -0
  10. helmkit-0.3.0/tests/test_parallel_load.py +42 -0
  11. {helmkit-0.2.0 → helmkit-0.3.0}/uv.lock +1 -1
  12. helmkit-0.2.0/src/helmkit/__init__.py +0 -5
  13. {helmkit-0.2.0 → helmkit-0.3.0}/.gitignore +0 -0
  14. {helmkit-0.2.0 → helmkit-0.3.0}/.python-version +0 -0
  15. {helmkit-0.2.0 → helmkit-0.3.0}/LICENSE +0 -0
  16. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/README.md +0 -0
  17. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/data/monomers.sdf +0 -0
  18. {helmkit-0.2.0 → helmkit-0.3.0}/benchmarks/data/peptides.csv +0 -0
  19. {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/data/monomers.sdf +0 -0
  20. {helmkit-0.2.0 → helmkit-0.3.0}/src/helmkit/py.typed +0 -0
  21. {helmkit-0.2.0 → helmkit-0.3.0}/tests/cycpeptmpdb.py +0 -0
  22. {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/generate_sdf.py +0 -0
  23. {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/monomers.csv +0 -0
  24. {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/monomers.sdf +0 -0
  25. {helmkit-0.2.0 → helmkit-0.3.0}/tests/data/peptides.csv +0 -0
  26. {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.2.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}$$$", monomer_df=custom_monomers)
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}$$$", monomer_df=custom_monomers)
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 row in df.iter_rows(named=True):
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 row in df.iter_rows(named=True):
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 row in df.iter_rows(named=True):
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)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "helmkit"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Parse HELM strings into RDKit molecules"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -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()
@@ -113,7 +113,7 @@ wheels = [
113
113
 
114
114
  [[package]]
115
115
  name = "helmkit"
116
- version = "0.1.0"
116
+ version = "0.3.0"
117
117
  source = { editable = "." }
118
118
  dependencies = [
119
119
  { name = "rdkit" },
@@ -1,5 +0,0 @@
1
- from .molecule import load_monomer_library
2
- from .molecule import Molecule
3
- from .molecule import SequenceConstants
4
-
5
- __all__ = ["Molecule", "load_monomer_library", "SequenceConstants"]
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