aamutils 0.0.7__tar.gz → 0.0.9__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.
- {aamutils-0.0.7 → aamutils-0.0.9}/PKG-INFO +14 -2
- {aamutils-0.0.7 → aamutils-0.0.9}/README.md +13 -0
- aamutils-0.0.9/aamutils/aam_expand.py +58 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/utils.py +12 -5
- {aamutils-0.0.7 → aamutils-0.0.9}/pyproject.toml +1 -1
- aamutils-0.0.9/test/test_aam_expand.py +36 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/.github/workflows/publish-package.yml +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/.github/workflows/test-and-lint.yml +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/.gitignore +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/LICENSE +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/Makefile +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/__init__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/__main__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/algorithm/__init__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/algorithm/aaming.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/algorithm/ilp.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/cmd/__init__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/cmd/expanding.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/aamutils/mapping.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/benchmark.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/conf.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/data/test_dataset.json +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/doc/getting_started.rst +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/doc/reference.rst +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/index.rst +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/lint.sh +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/make.bat +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/requirements.txt +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/test/__init__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/test/algorithm/__init__.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/test/algorithm/test_aaming.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/test/algorithm/test_ilp.py +0 -0
- {aamutils-0.0.7 → aamutils-0.0.9}/test/test_mapping.py +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: aamutils
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.9
|
|
4
4
|
Summary: Collection of atom-atom-mapping utility functions.
|
|
5
5
|
Project-URL: homepage, https://github.com/klausweinbauer/AAMUtils
|
|
6
6
|
Project-URL: source, https://github.com/klausweinbauer/AAMUtils
|
|
7
7
|
Project-URL: issues, https://github.com/klausweinbauer/AAMUtils/issues
|
|
8
8
|
Author-email: Klaus Weinbauer <klaus@bioinf.uni-leipzig.de>
|
|
9
|
-
License-File: LICENSE
|
|
10
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -35,6 +34,8 @@ pip install aamutils
|
|
|
35
34
|
|
|
36
35
|
## Usage
|
|
37
36
|
|
|
37
|
+
### Use in command line
|
|
38
|
+
|
|
38
39
|
The input is a list of partial atom-atom-maps (AAMs). Data is read line-by-line
|
|
39
40
|
from a text file. Each line should contain one reaction SMILES.
|
|
40
41
|
|
|
@@ -69,6 +70,17 @@ cat testinput_extended.json
|
|
|
69
70
|
}
|
|
70
71
|
]
|
|
71
72
|
```
|
|
73
|
+
### Use in script
|
|
74
|
+
```python
|
|
75
|
+
from aamutils.aam_expand import extend_aam_from_rsmi
|
|
76
|
+
|
|
77
|
+
rsmi = "CC[CH2:3][Cl:1].[N:2]>>CC[CH2:3][N:2].[Cl:1]"
|
|
78
|
+
|
|
79
|
+
result_smiles = extend_aam_from_rsmi(rsmi)
|
|
80
|
+
|
|
81
|
+
print(result_smiles)
|
|
82
|
+
>>> "[Cl:1][CH2:3][CH2:5][CH3:4].[NH3:2]>>[ClH:1].[NH2:2][CH2:3][CH2:5][CH3:4]"
|
|
83
|
+
```
|
|
72
84
|
|
|
73
85
|
## Benchmark
|
|
74
86
|
|
|
@@ -13,6 +13,8 @@ pip install aamutils
|
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
|
+
### Use in command line
|
|
17
|
+
|
|
16
18
|
The input is a list of partial atom-atom-maps (AAMs). Data is read line-by-line
|
|
17
19
|
from a text file. Each line should contain one reaction SMILES.
|
|
18
20
|
|
|
@@ -47,6 +49,17 @@ cat testinput_extended.json
|
|
|
47
49
|
}
|
|
48
50
|
]
|
|
49
51
|
```
|
|
52
|
+
### Use in script
|
|
53
|
+
```python
|
|
54
|
+
from aamutils.aam_expand import extend_aam_from_rsmi
|
|
55
|
+
|
|
56
|
+
rsmi = "CC[CH2:3][Cl:1].[N:2]>>CC[CH2:3][N:2].[Cl:1]"
|
|
57
|
+
|
|
58
|
+
result_smiles = extend_aam_from_rsmi(rsmi)
|
|
59
|
+
|
|
60
|
+
print(result_smiles)
|
|
61
|
+
>>> "[Cl:1][CH2:3][CH2:5][CH3:4].[NH3:2]>>[ClH:1].[NH2:2][CH2:3][CH2:5][CH3:4]"
|
|
62
|
+
```
|
|
50
63
|
|
|
51
64
|
## Benchmark
|
|
52
65
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import networkx as nx
|
|
2
|
+
import rdkit.Chem.rdmolfiles as rdmolfiles
|
|
3
|
+
from aamutils.algorithm.ilp import expand_partial_aam_balanced
|
|
4
|
+
from aamutils.utils import smiles_to_graph, graph_to_mol, set_aam
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def extend_aam_from_graph(G: nx.Graph, H: nx.Graph) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Extends atom-atom mappings (AAM) from two input graphs,
|
|
10
|
+
G (reactants) and H (products),by solving the AAM problem using an
|
|
11
|
+
Integer Linear Programming (ILP) approach and generating
|
|
12
|
+
a reaction SMILES (RSMI) string.
|
|
13
|
+
|
|
14
|
+
Parameters:
|
|
15
|
+
- G (nx.Graph): Graph representing the reactants.
|
|
16
|
+
Nodes should contain necessary attributes for AAM.
|
|
17
|
+
- H (nx.Graph): Graph representing the products.
|
|
18
|
+
Nodes should contain necessary attributes for AAM.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
- str: A reaction SMILES string (RSMI) in the format 'reactant>>product'
|
|
22
|
+
with extended atom mappings.
|
|
23
|
+
"""
|
|
24
|
+
# Solve the partial AAM problem using ILP and retrieve the mapping matrix
|
|
25
|
+
M, _, _ = expand_partial_aam_balanced(G, H)
|
|
26
|
+
|
|
27
|
+
# Apply the AAM matrix to the graphs
|
|
28
|
+
set_aam(G, H, M)
|
|
29
|
+
|
|
30
|
+
# Convert the modified graphs back to RDKit molecules
|
|
31
|
+
r_mol = graph_to_mol(G)
|
|
32
|
+
p_mol = graph_to_mol(H)
|
|
33
|
+
|
|
34
|
+
# Generate reaction SMILES string from the RDKit molecules
|
|
35
|
+
result_smiles = "{}>>{}".format(
|
|
36
|
+
rdmolfiles.MolToSmiles(
|
|
37
|
+
r_mol, canonical=True, kekuleSmiles=False, allHsExplicit=True
|
|
38
|
+
),
|
|
39
|
+
rdmolfiles.MolToSmiles(
|
|
40
|
+
p_mol, canonical=True, kekuleSmiles=False, allHsExplicit=True
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
return result_smiles
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def extend_aam_from_rsmi(rsmi: str) -> str:
|
|
47
|
+
"""
|
|
48
|
+
Extends atom-atom mappings (AAM) from a reaction SMILES (RSMI) string,
|
|
49
|
+
and returns the resulting reaction SMILES string.
|
|
50
|
+
|
|
51
|
+
Parameters:
|
|
52
|
+
- rsmi (str): A reaction SMILES string in the format 'reactant>>product'.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
- str: A reaction SMILES string with extended atom mappings.
|
|
56
|
+
"""
|
|
57
|
+
G, H = smiles_to_graph(rsmi)
|
|
58
|
+
return extend_aam_from_graph(G, H)
|
|
@@ -17,7 +17,10 @@ def mol_to_graph(mol: Chem.rdchem.Mol) -> nx.Graph:
|
|
|
17
17
|
g = nx.Graph()
|
|
18
18
|
for atom in mol.GetAtoms():
|
|
19
19
|
aam = atom.GetAtomMapNum()
|
|
20
|
-
|
|
20
|
+
formal_charge = atom.GetFormalCharge() # Get the formal charge of the atom
|
|
21
|
+
g.add_node(
|
|
22
|
+
atom.GetIdx(), symbol=atom.GetSymbol(), aam=aam, formal_charge=formal_charge
|
|
23
|
+
) # Store formal charge
|
|
21
24
|
for bond in mol.GetBonds():
|
|
22
25
|
bond_type = str(bond.GetBondType()).split(".")[-1]
|
|
23
26
|
bond_order = 1
|
|
@@ -27,14 +30,16 @@ def mol_to_graph(mol: Chem.rdchem.Mol) -> nx.Graph:
|
|
|
27
30
|
return g
|
|
28
31
|
|
|
29
32
|
|
|
30
|
-
def smiles_to_graph(
|
|
33
|
+
def smiles_to_graph(
|
|
34
|
+
smiles: str, sanitize: bool = True
|
|
35
|
+
) -> nx.Graph | tuple[nx.Graph, nx.Graph]:
|
|
31
36
|
if ">>" in smiles:
|
|
32
37
|
smiles_token = smiles.split(">>")
|
|
33
|
-
g = mol_to_graph(rdmolfiles.MolFromSmiles(smiles_token[0]))
|
|
34
|
-
h = mol_to_graph(rdmolfiles.MolFromSmiles(smiles_token[1]))
|
|
38
|
+
g = mol_to_graph(rdmolfiles.MolFromSmiles(smiles_token[0], sanitize=sanitize))
|
|
39
|
+
h = mol_to_graph(rdmolfiles.MolFromSmiles(smiles_token[1], sanitize=sanitize))
|
|
35
40
|
return g, h
|
|
36
41
|
else:
|
|
37
|
-
return mol_to_graph(rdmolfiles.MolFromSmiles(smiles))
|
|
42
|
+
return mol_to_graph(rdmolfiles.MolFromSmiles(smiles, sanitize=sanitize))
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
def graph_to_mol(
|
|
@@ -54,6 +59,8 @@ def graph_to_mol(
|
|
|
54
59
|
idx_map[n] = idx
|
|
55
60
|
if aam_key in d.keys() and d[aam_key] >= 0:
|
|
56
61
|
rw_mol.GetAtomWithIdx(idx).SetAtomMapNum(d[aam_key])
|
|
62
|
+
if "formal_charge" in d: # Set the formal charge for the atom
|
|
63
|
+
rw_mol.GetAtomWithIdx(idx).SetFormalCharge(d["formal_charge"])
|
|
57
64
|
for n1, n2, d in G.edges(data=True):
|
|
58
65
|
idx1 = idx_map[n1]
|
|
59
66
|
idx2 = idx_map[n2]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from aamutils.utils import smiles_to_graph
|
|
3
|
+
from aamutils.aam_expand import extend_aam_from_graph, extend_aam_from_rsmi
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestExtendAAMFromGraph(unittest.TestCase):
|
|
7
|
+
def test_extend_aam_from_graph(self):
|
|
8
|
+
"""
|
|
9
|
+
Tests the extend_aam_from_graph function to ensure it correctly extends
|
|
10
|
+
atom-atom mappings and returns the expected reaction SMILES.
|
|
11
|
+
"""
|
|
12
|
+
rsmi = "CC[CH2:3][Cl:1].[N:2]>>CC[CH2:3][N:2].[Cl:1]"
|
|
13
|
+
G, H = smiles_to_graph(rsmi)
|
|
14
|
+
result_smiles = extend_aam_from_graph(G, H)
|
|
15
|
+
expected = (
|
|
16
|
+
"[Cl:1][CH2:3][CH2:5][CH3:4].[NH3:2]>>[ClH:1].[NH2:2][CH2:3][CH2:5][CH3:4]"
|
|
17
|
+
)
|
|
18
|
+
self.assertEqual(result_smiles, expected)
|
|
19
|
+
|
|
20
|
+
def test_extend_aam_from_smiles(self):
|
|
21
|
+
"""
|
|
22
|
+
Tests the extend_aam_from_graph function to ensure it correctly extends
|
|
23
|
+
atom-atom mappings and returns the expected reaction SMILES.
|
|
24
|
+
"""
|
|
25
|
+
rsmi = "CC[CH2:3][Cl:1].[N:2]>>CC[CH2:3][N:2].[Cl:1]"
|
|
26
|
+
|
|
27
|
+
result_smiles = extend_aam_from_rsmi(rsmi)
|
|
28
|
+
expected = (
|
|
29
|
+
"[Cl:1][CH2:3][CH2:5][CH3:4].[NH3:2]>>[ClH:1].[NH2:2][CH2:3][CH2:5][CH3:4]"
|
|
30
|
+
)
|
|
31
|
+
self.assertEqual(result_smiles, expected)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Run the unittest
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
unittest.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
|
|
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
|