<jupyter_start><jupyter_text>Creating a fragment library from fragments To create a fragment library, we need a fragment db. You can create a fragment db from a given list of SMILES using 'CReM' - https://github.com/DrrDom/crem. We used a fragment db generated from a list of ZINC molecules for this tutorial. The goal of this tutorial is to select fragments that are appropriate for fragment-based generation.<jupyter_code>import sqlite3
import pandas as pd 
from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem.Draw import MolDrawing, DrawingOptions<jupyter_output><empty_output><jupyter_text>First, we open the fragment db using sqlite.<jupyter_code>connection = sqlite3.connect("fragments.db")
cur = connection.cursor()<jupyter_output><empty_output><jupyter_text>Then, we query fragments in given condition. Here, we only consider fragments that appear at least twice in the db ('freq > 1').<jupyter_code>radius = 2
min_atoms, max_atoms = 1, 16
sql = f"""SELECT core_smi
          FROM radius{radius}
          WHERE core_num_atoms BETWEEN ? AND ?
          AND freq > 1"""
cur.execute(sql, (min_atoms, max_atoms))
motifs = cur.fetchall()
len(list(motifs)), len(set(list(motifs)))
frag_samples = [[l[0], Chem.MolFromSmiles(l[0])] for l in list(set(motifs))]
frag_samples = pd.DataFrame(frag_samples).set_axis(['frag', 'mol'], axis=1, inplace=False)<jupyter_output><empty_output><jupyter_text>Let's take a look on some...<jupyter_code>Draw.MolsToGridImage(frag_samples.iloc[:50].loc[frag_samples['mol']!=None]['mol'], subImgSize=(300,200),molsPerRow=10)<jupyter_output><empty_output><jupyter_text>Now, we need to filter out the duplicates. If two fragments with same structure have different attachment sites, we leave the one that has the largest number of attachment sites.<jupyter_code>def get_num_att_points(m):
    atoms = m.GetAtoms()
    att_points = []
    for a in atoms:
        atom_idx = a.GetIdx()
        atom_symbol = a.GetSymbol()
        if atom_symbol == '*':
            att_points.append(atom_idx)
    return len(att_points)
    
att = Chem.MolFromSmiles('*')
H = Chem.MolFromSmiles('[H]')
frag_samples['canon'] = frag_samples['mol'].apply(lambda m: Chem.ReplaceSubstructs(m, att, H, replaceAll=True)[0])
frag_samples['canon_smiles'] = frag_samples['canon'].apply(Chem.RemoveHs)
frag_samples['canon_smiles'] = frag_samples['canon_smiles'].apply(Chem.MolToSmiles)
frag_samples['num_att'] = frag_samples['mol'].apply(get_num_att_points)
_frag_samples = frag_samples[['frag', 'mol', 'canon_smiles', 'num_att']].groupby(by='canon_smiles')<jupyter_output><empty_output><jupyter_text>We now see that there are 455 unique fragments out of 825 fragments. Fragments are grouped by their structures (without attachment points).<jupyter_code>len(_frag_samples.groups)
_frag_samples.groups<jupyter_output><empty_output><jupyter_text>Let's only keep the fragments that have the most attachment sites.<jupyter_code>cleaned_frags = pd.concat([group.sort_values(by='num_att').tail(1) for name, group in _frag_samples], ignore_index=True)<jupyter_output><empty_output><jupyter_text>Remove unsanitizable molecules.<jupyter_code>cleaned_frags['if_sane'] = cleaned_frags['mol'].apply(Chem.SanitizeMol)
cleaned_frags = cleaned_frags.loc[cleaned_frags['if_sane']==0]
print(len(cleaned_frags))
frags = cleaned_frags[['frag']]
frags.to_csv('motifs_from_zinc.txt',index=False)<jupyter_output><empty_output><jupyter_text>We can randomly sample a fixed number of fragments and save those in txt file.<jupyter_code>frags.sample(n=80).to_csv('motifs_from_zinc_80.txt', index=False)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1190606226105953, 'fraction_numerical': 0.009284543965046422, 'mean_word_length': 6.744186046511628, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 39, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '377300', 'license': 'Apache-2.0', 'n_tokens_mistral': 1280, 'n_tokens_neox': 1224, 'n_words': 287, 'path': 'gen_frag_lib.ipynb', 'repo_name': 'AITRICS/FREED', 'size': '3662'}