frag = '*c1c(C)cccc1C'
print(count_dummies(mol_from_smiles(frag)))1
count_dummies (mol:rdkit.Chem.rdchem.Mol)
Function to count dummy atoms.
| Type | Details | |
|---|---|---|
| mol | Mol | input molecule |
| Returns | int | count of dummy atoms |
Unit Tests
get_size (frag:rdkit.Chem.rdchem.Mol)
Function to count real atoms.
| Type | Details | |
|---|---|---|
| frag | Mol | input fragment |
| Returns | int | count of real atoms |
Unit Tests
replace_last (s:str, old:str, new:str)
Function to replace the last occuring dummy label with a fragment.
| Type | Details | |
|---|---|---|
| s | str | the string (fragment) to which the dummy label * is to be replaced with another fragment |
| old | str | the string from the fragment s to be replaced |
| new | str | the string to replace the ‘old’ string in the fragment s |
| Returns | str | the original string s with the replacement |
s = 'N(*)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
old = '*'
new = 'c1c(C)cccc1C'
print(replace_last(s, old, new))N(c1c(C)cccc1C)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1
C(N*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1
Unit Tests
check_reconstruction (frags:list[str], frag_1:str, frag_2:str, orig_smi)
Function to test whether the original molecule has been reconstructed.
| Type | Details | |
|---|---|---|
| frags | list | list of fragments in SMILES format |
| frag_1 | str | head/tail fragment in SMILES format |
| frag_2 | str | head/tail fragment in SMILES format |
| orig_smi | original molecule in SMILES format | |
| Returns | bool | whether the original molecule was reconstructed |
frags = []
frag_1 = '*CCC'
frag_2 = 'N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
orig_smi = 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
print(check_reconstruction(frags, frag_1, frag_2, orig_smi))True
frags = ['*c1c(C)cccc1C', '*N*', '*CC(*)=O']
frag_1 = '*C1CC[NH+](*)CC1'
frag_2 = 'O(*)Cc1ccc(F)cc1'
orig_smi = 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
print(check_reconstruction(frags, frag_1, frag_2, orig_smi))True
Unit Tests
test_eq(check_reconstruction([], '*CCC', 'N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'), True)
test_eq(check_reconstruction(['*c1c(C)cccc1C', '*N*', '*CC(*)=O'], '*C1CC[NH+](*)CC1', 'O(*)Cc1ccc(F)cc1', 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'), True)
test_fail(check_reconstruction([], '*CCC', 'N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', 'C(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'))check_bond_no (bonds:list, frags:list, frag_list_len:int, smi:str, verbose:int=0)
This function checks if the molecule has less bonds than the limit of BRIC bonds.
| Type | Default | Details | |
|---|---|---|---|
| bonds | list | the list of BRIC bonds locations | |
| frags | list | the list of fragments | |
| frag_list_len | int | the length of the fragment list | |
| smi | str | the smiles string of the molecule | |
| verbose | int | 0 | print fragmentation process, set verbose to 1 |
| Returns | tuple | a tuple containing the fragment list and a boolean value to indicate whether fragmentation is complete |
bonds = []
frags = ['*c1c(C)cccc1C', '*N*', '*CC(*)=O', '*C1CC[NH+](*)CC1', '*O*', '*C*', 'c1(*)ccc(F)cc1']
frags_list_len = 0
smi = 'c1(*)ccc(F)cc1'
print(check_bond_no(bonds, frags, frags_list_len, smi))(['*c1c(C)cccc1C', '*N*', '*CC(*)=O', '*C1CC[NH+](*)CC1', '*O*', '*C*', 'c1(*)ccc(F)cc1', 'c1(*)ccc(F)cc1'], True)
bonds = [((9, 8), ('1', '5')), ((16, 17), ('3', '4')), ((16, 15), ('3', '15')), ((11, 12), ('4', '5')), ((8, 7), ('5', '16')), ((17, 18), ('8', '16'))]
frags = []
frags_list_len = 0
smi = 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
print(check_bond_no(bonds, frags, frags_list_len, smi))([], False)
Unit Tests
test_eq(check_bond_no([], ['*c1c(C)cccc1C', '*N*', '*CC(*)=O', '*C1CC[NH+](*)CC1', '*O*', '*C*', 'c1(*)ccc(F)cc1'], 0, 'c1(*)ccc(F)cc1'),(['*c1c(C)cccc1C', '*N*', '*CC(*)=O', '*C1CC[NH+](*)CC1', '*O*', '*C*', 'c1(*)ccc(F)cc1', 'c1(*)ccc(F)cc1'], True))
test_eq(check_bond_no([((9, 8), ('1', '5')), ((16, 17), ('3', '4')), ((16, 15), ('3', '15')), ((11, 12), ('4', '5')), ((8, 7), ('5', '16')), ((17, 18), ('8', '16'))], [], 0, 'c1(*)ccc(F)cc1'),([], False))fragment_recursive (smi_orig:str, smi:str, frags:list, counter:int, frag_list_len:int, min_length:int=0, verbose:int=0)
This recursive function fragments a molecule using the DEFRAGMO fragmentation method.
| Type | Default | Details | |
|---|---|---|---|
| smi_orig | str | the original smiles string of the molecule | |
| smi | str | the smiles string of the molecule | |
| frags | list | the list of fragments | |
| counter | int | the counter for the recursion | |
| frag_list_len | int | the length of the fragment list | |
| min_length | int | 0 | the minimum number of atoms in a fragment |
| verbose | int | 0 | print fragmentation process, set verbose to 1 |
| Returns | list | the list of fragments |
smi = 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
frags = []
print(fragment_recursive(smi, smi, frags, 0, 0, min_length=0, verbose=1))Head fragment: *CCC
Recurse tail: N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Tail: *CCc1cccc(-c2ccccc2)c1
Recurse Head: N(*)(*)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *N(*)*
Recurse tail: C(*)(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *C(*)=O
Recurse tail: C1(*)OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *NC1C(N)C=C(C(=O)O)OC1*
Recurse tail: C(*)(C)=O
Final Fragment: C(*)(C)=O
['*CCC', '*CCc1cccc(-c2ccccc2)c1', '*N(*)*', '*C(*)=O', '*NC1C(N)C=C(C(=O)O)OC1*', 'C(*)(C)=O']
smi = 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
frags = []
print(fragment_recursive(smi, smi, frags, 0, 0, min_length=3, verbose=1))Head fragment: *CCC
Recurse tail: N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Tail: *CCc1cccc(-c2ccccc2)c1
Recurse Head: N(*)(*)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *C(=O)N(*)*
Recurse tail: C1(*)OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *NC1C(N)C=C(C(=O)O)OC1*
Recurse tail: C(*)(C)=O
Final Fragment: C(*)(C)=O
['*CCC', '*CCc1cccc(-c2ccccc2)c1', '*C(=O)N(*)*', '*NC1C(N)C=C(C(=O)O)OC1*', 'C(*)(C)=O']
smi = 'COc1ccc(C(=O)Nc2cc(C(C)C)c(O)c(S(=O)(=O)c3ccc(OC)cc3)c2C)cc1'
frags = []
print(fragment_recursive(smi, smi, frags, 0, 0, min_length=0, verbose=1))Head fragment: *OC
Recurse tail: c1(*)ccc(C(=O)Nc2cc(C(C)C)c(O)c(S(=O)(=O)c3ccc(OC)cc3)c2C)cc1
Head fragment: *c1ccc(*)cc1
Recurse tail: C(*)(=O)Nc1cc(C(C)C)c(O)c(S(=O)(=O)c2ccc(OC)cc2)c1C
Head fragment: *C(*)=O
Recurse tail: N(*)c1cc(C(C)C)c(O)c(S(=O)(=O)c2ccc(OC)cc2)c1C
Head fragment: *N*
Recurse tail: c1(*)cc(C(C)C)c(O)c(S(=O)(=O)c2ccc(OC)cc2)c1C
Tail: *C(C)C
Recurse Head: c1(*)cc(*)c(O)c(S(=O)(=O)c2ccc(OC)cc2)c1C
Head fragment: *c1ccc(S(=O)(=O)c2c(C)c(*)cc(*)c2O)cc1
Recurse tail: O(*)C
Final Fragment: O(*)C
['*OC', '*c1ccc(*)cc1', '*C(*)=O', '*N*', '*C(C)C', '*c1ccc(S(=O)(=O)c2c(C)c(*)cc(*)c2O)cc1', 'O(*)C']
Unit Tests
test_eq(fragment_recursive('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', [], 0, 0, min_length=0), ['*CCC', '*CCc1cccc(-c2ccccc2)c1', '*N(*)*', '*C(*)=O', '*NC1C(N)C=C(C(=O)O)OC1*', 'C(*)(C)=O'])
test_eq(fragment_recursive('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', [], 0, 0, min_length=3), ['*CCC', '*CCc1cccc(-c2ccccc2)c1', '*C(=O)N(*)*', '*NC1C(N)C=C(C(=O)O)OC1*', 'C(*)(C)=O'])
test_eq(fragment_recursive('COc1ccc(C(=O)Nc2cc(C(C)C)c(O)c(S(=O)(=O)c3ccc(OC)cc3)c2C)cc1', 'COc1ccc(C(=O)Nc2cc(C(C)C)c(O)c(S(=O)(=O)c3ccc(OC)cc3)c2C)cc1', [], 0, 0, min_length=0), ['*OC', '*c1ccc(*)cc1', '*C(*)=O', '*N*', '*C(C)C', '*c1ccc(S(=O)(=O)c2c(C)c(*)cc(*)c2O)cc1', 'O(*)C'])break_into_fragments_defragmo (smi:str, min_length:int=0, verbose:int=0)
This function breaks a molecule into fragments using the DEFRAGMO fragmentation method.
| Type | Default | Details | |
|---|---|---|---|
| smi | str | the smiles string of the molecule | |
| min_length | int | 0 | the minimum number of atoms in a fragment |
| verbose | int | 0 | print fragmentation process, set verbose to 1 |
| Returns | tuple | a tuple containing the original smiles, the fragmented smiles, and the number of fragments |
smi = 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
break_into_fragments_defragmo(smi, min_length=0, verbose=1)Head fragment: *CCC
Recurse tail: N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Tail: *CCc1cccc(-c2ccccc2)c1
Recurse Head: N(*)(*)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *N(*)*
Recurse tail: C(*)(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *C(*)=O
Recurse tail: C1(*)OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *NC1C(N)C=C(C(=O)O)OC1*
Recurse tail: C(*)(C)=O
Final Fragment: C(*)(C)=O
('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O',
'*CCC *CCc1cccc(-c2ccccc2)c1 *N(*)* *C(*)=O *NC1C(N)C=C(C(=O)O)OC1* C(*)(C)=O',
6)
smi = 'CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'
break_into_fragments_defragmo(smi, min_length=3, verbose=1)Head fragment: *CCC
Recurse tail: N(*)(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Tail: *CCc1cccc(-c2ccccc2)c1
Recurse Head: N(*)(*)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *C(=O)N(*)*
Recurse tail: C1(*)OC(C(=O)O)=CC(N)C1NC(C)=O
Head fragment: *NC1C(N)C=C(C(=O)O)OC1*
Recurse tail: C(*)(C)=O
Final Fragment: C(*)(C)=O
('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O',
'*CCC *CCc1cccc(-c2ccccc2)c1 *C(=O)N(*)* *NC1C(N)C=C(C(=O)O)OC1* C(*)(C)=O',
5)
smi = 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
break_into_fragments_defragmo(smi, min_length=0, verbose=1)Head fragment: *c1c(C)cccc1C
Recurse tail: N(*)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1
Head fragment: *N*
Recurse tail: C(*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1
Head fragment: *CC(*)=O
Recurse tail: [NH+]1(*)CCC(OCc2ccc(F)cc2)CC1
Head fragment: *C1CC[NH+](*)CC1
Recurse tail: O(*)Cc1ccc(F)cc1
Head fragment: *O*
Recurse tail: C(*)c1ccc(F)cc1
Head fragment: *C*
Recurse tail: c1(*)ccc(F)cc1
Final Fragment: c1(*)ccc(F)cc1
('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1',
'*c1c(C)cccc1C *N* *CC(*)=O *C1CC[NH+](*)CC1 *O* *C* c1(*)ccc(F)cc1',
7)
smi = 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
break_into_fragments_defragmo(smi, min_length=3, verbose=1)Head fragment: *c1c(C)cccc1C
Recurse tail: N(*)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1
Head fragment: *CC(=O)N*
Recurse tail: [NH+]1(*)CCC(OCc2ccc(F)cc2)CC1
Head fragment: *C1CC[NH+](*)CC1
Recurse tail: O(*)Cc1ccc(F)cc1
Final Fragment: O(*)Cc1ccc(F)cc1
('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1',
'*c1c(C)cccc1C *CC(=O)N* *C1CC[NH+](*)CC1 O(*)Cc1ccc(F)cc1',
4)
Unit Tests
test_eq(break_into_fragments_defragmo('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O'), ('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', '*CCC *CCc1cccc(-c2ccccc2)c1 *N(*)* *C(*)=O *NC1C(N)C=C(C(=O)O)OC1* C(*)(C)=O', 6))
test_eq(break_into_fragments_defragmo('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', min_length=3), ('CCCN(CCc1cccc(-c2ccccc2)c1)C(=O)C1OC(C(=O)O)=CC(N)C1NC(C)=O', '*CCC *CCc1cccc(-c2ccccc2)c1 *C(=O)N(*)* *NC1C(N)C=C(C(=O)O)OC1* C(*)(C)=O', 5))
test_eq(break_into_fragments_defragmo('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'), ('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1', '*c1c(C)cccc1C *N* *CC(*)=O *C1CC[NH+](*)CC1 *O* *C* c1(*)ccc(F)cc1', 7))
test_eq(break_into_fragments_defragmo('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1', min_length=3), ('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1', '*c1c(C)cccc1C *CC(=O)N* *C1CC[NH+](*)CC1 O(*)Cc1ccc(F)cc1', 4))