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.
Files changed (29) hide show
  1. helmkit-0.3.1/.github/workflows/main.yml +22 -0
  2. {helmkit-0.3.0 → helmkit-0.3.1}/PKG-INFO +52 -1
  3. {helmkit-0.3.0 → helmkit-0.3.1}/README.md +51 -0
  4. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/README.md +10 -7
  5. {helmkit-0.3.0 → helmkit-0.3.1}/pyproject.toml +2 -1
  6. {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/molecule.py +8 -5
  7. helmkit-0.3.1/tests/backup +66 -0
  8. helmkit-0.3.1/tests/test_cycpeptmpdb.py +29 -0
  9. helmkit-0.3.1/tests/test_parallel_load.py +28 -0
  10. helmkit-0.3.0/tests/random_peptides.py → helmkit-0.3.1/tests/test_random_peptides.py +3 -4
  11. {helmkit-0.3.0 → helmkit-0.3.1}/uv.lock +54 -0
  12. helmkit-0.3.0/tests/cycpeptmpdb.py +0 -43
  13. helmkit-0.3.0/tests/test_parallel_load.py +0 -42
  14. {helmkit-0.3.0 → helmkit-0.3.1}/.gitignore +0 -0
  15. {helmkit-0.3.0 → helmkit-0.3.1}/.python-version +0 -0
  16. {helmkit-0.3.0 → helmkit-0.3.1}/LICENSE +0 -0
  17. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/data/monomers.sdf +0 -0
  18. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/data/peptides.csv +0 -0
  19. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-benchmark.py +0 -0
  20. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-parallel-benchmark.py +0 -0
  21. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/helmkit-with-reload-benchmark.py +0 -0
  22. {helmkit-0.3.0 → helmkit-0.3.1}/benchmarks/pypept-benchmark.py +0 -0
  23. {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/__init__.py +0 -0
  24. {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/data/monomers.sdf +0 -0
  25. {helmkit-0.3.0 → helmkit-0.3.1}/src/helmkit/py.typed +0 -0
  26. {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/generate_sdf.py +0 -0
  27. {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/monomers.csv +0 -0
  28. {helmkit-0.3.0 → helmkit-0.3.1}/tests/data/monomers.sdf +0 -0
  29. {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.0
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` | 676.65 | 0.144 |
39
- | `helmkit` | 3.60 | 0.00077 |
40
- | `helmkit` (DB reload every peptide) | 261.81 | 0.056 |
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.1.0` (local development version)
58
+ - `helmkit 0.3.0` (local development version)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "helmkit"
3
- version = "0.3.0"
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
- default_monomer_df_filepath = files(SequenceConstants.def_path).joinpath(
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 main():
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
- if inchi1 != inchi2:
19
- raise ValueError(f"{inchi1} != {inchi2}")
18
+ assert inchi1 == inchi2
20
19
 
21
20
 
22
21
  if __name__ == "__main__":
23
- main()
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