Fragmentation

Fragmentation module

source

count_dummies

 count_dummies (mol:rdkit.Chem.rdchem.Mol)

Function to count dummy atoms.

Type Details
mol Mol input molecule
Returns int count of dummy atoms
frag = '*c1c(C)cccc1C'
print(count_dummies(mol_from_smiles(frag)))
1
frag = '*NC(*)C'
print(count_dummies(mol_from_smiles(frag)))
2

Unit Tests

test_eq(count_dummies(mol_from_smiles('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1')),0)
test_eq(count_dummies(mol_from_smiles('*c1c(C)cccc1C')),1)
test_eq(count_dummies(mol_from_smiles('*NC(*)C')),2)

source

get_size

 get_size (frag:rdkit.Chem.rdchem.Mol)

Function to count real atoms.

Type Details
frag Mol input fragment
Returns int count of real atoms
frag = '*c1c(C)cccc1C'
print(get_size(mol_from_smiles(frag)))
8
frag = '*NC(*)C'
print(get_size(mol_from_smiles(frag)))
3
smi = 'Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
print(get_size(mol_from_smiles(smi)))
27

Unit Tests

test_eq(get_size(mol_from_smiles('*c1c(C)cccc1C')), 8)
test_eq(get_size(mol_from_smiles('*NC(*)C')), 3)
test_eq(get_size(mol_from_smiles('Cc1cccc(C)c1NC(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1')), 27)

source

replace_last

 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
s = 'C(*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1'
old = '*'
new = 'N*'
print(replace_last(s, old, new))
C(N*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1

Unit Tests

test_eq(replace_last('N(*)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1', '*', 'c1c(C)cccc1C'),
        'N(c1c(C)cccc1C)C(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1')
test_eq(replace_last('C(*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1', '*', 'N*'),
        'C(N*)(=O)C[NH+]1CCC(OCc2ccc(F)cc2)CC1')

source

check_reconstruction

 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'))

source

check_bond_no

 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))

source

fragment_recursive

 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'])

source

break_into_fragments_defragmo

 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))