<jupyter_start><jupyter_text>Load the SD file with the top 10K hits from the OpenEye docking of Enamine REAL into SARS Cov-2 Mpro<jupyter_code>df = PandasTools.LoadSDF("Giga_Docking_10K_Hit_List.sdf.gz")
df.head()<jupyter_output><empty_output><jupyter_text>It appears that PandasTools reads in all of the tag fields as object.  Need to convert our scores to float.<jupyter_code>df.Chemgauss4 = df.Chemgauss4.astype(np.float64)<jupyter_output><empty_output><jupyter_text>Look at the distribution of Chemgauss4<jupyter_code>sns.distplot(df.Chemgauss4)<jupyter_output><empty_output><jupyter_text>Look at the distribution of scores across Enamine REAL reactions. Calculate the mean score for each reaction so that we can order the plot to make it easier to read.<jupyter_code>mean_list = []
for k,v in df.groupby("reaction"):
    mean_list.append([k,v.Chemgauss4.mean()])
mean_list.sort(key=itemgetter(1))
sorted_keys = [x[0] for x in mean_list]
sns.set(rc={'figure.figsize': (15, 12)})
sns.set(font_scale=1.0)
sns.set_style('whitegrid')<jupyter_output><empty_output><jupyter_text>Plot scores as a function of reaction to see if some reactions give the best scoring molecules<jupyter_code>sns.boxplot("Chemgauss4","reaction",data=df,orient='h',order=sorted_keys)
protein = next(oddt.toolkit.readfile('pdb', 'covid.pdb'))<jupyter_output><empty_output><jupyter_text>Don't run the cell below.  The oddt will take about 5 minutes to generate a useless picture of the protein.<jupyter_code>#protein
np.set_printoptions(precision=2)<jupyter_output><empty_output><jupyter_text>Generate interaction fingerprints for the docked strctures<jupyter_code>%%time
fp_list = []
for mol in tqdm(df.ROMol):
    od_mol = oddt.toolkit.Molecule(mol)
    fp_list.append(PLEC(od_mol,protein))<jupyter_output><empty_output><jupyter_text>Add the fingerprint to the dataframe<jupyter_code>df['fp'] = fp_list<jupyter_output><empty_output><jupyter_text>Convert the sparse fingerprints to dense, this appears to make the distance calculation below a lot faster.<jupyter_code>df['dense'] = [sparse_to_dense(x,size=16384) for x in fp_list]<jupyter_output><empty_output><jupyter_text>Create a new dataframe from the high scoring molecules<jupyter_code>active_df = df.query("Chemgauss4 <= -13").copy()
active_df.shape<jupyter_output><empty_output><jupyter_text>Calculate a distance matrix for clustering<jupyter_code>%%time
nfps = active_df.shape[0]
dists = []
for i in tqdm(range(1,nfps)):
    for j in range(i):
        dists.append(1-dice(df.dense[i],df.dense[j],sparse=False))
len(dists)<jupyter_output><empty_output><jupyter_text>Cluster using the Taylor Butina method<jupyter_code>cs = Butina.ClusterData(dists,nfps,0.35,isDistData=True)<jupyter_output><empty_output><jupyter_text>See how many clusters we have<jupyter_code>len(pd.Series(cs).unique())<jupyter_output><empty_output><jupyter_text>Create a new column with the cluster ID<jupyter_code>cluster = [-1] * active_df.shape[0]
for idx,c in enumerate(cs):
    for member in c:
        cluster[member] = idx
active_df['cluster'] = cluster<jupyter_output><empty_output><jupyter_text>View the clusters<jupyter_code>@interact(cluster_id=active_df.cluster.value_counts().index)
def show_cluster(cluster_id):
    num_samples = 20
    cluster_df = active_df.query(f"cluster == {cluster_id}")
    num_samples = min(cluster_df.shape[0],num_samples)
    mol_list = cluster_df.ROMol.sample(num_samples)
    p = py3Dmol.view(500, 500)
    for mol in mol_list:
        molblock = Chem.MolToMolBlock(mol)
        p.addModel(molblock, 'mol')
        p.setStyle({'stick' : {}})
    p.setBackgroundColor('0xeeeeee')
    p.zoomTo()
    return p<jupyter_output><empty_output><jupyter_text>Write the first 20 molecules from the first 10 clusters to disk<jupyter_code>for idx,cluster_id in enumerate(active_df.cluster.value_counts()[:10].index):
    file_name = f"cluster_{idx:03d}_{cluster_id}.sdf"
    writer = Chem.SDWriter(file_name)
    for mol in active_df.query(f"cluster == {cluster_id}").ROMol[:20]:
        writer.write(mol)
    writer.close()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11891362857841938, 'fraction_numerical': 0.014680694886224614, 'mean_word_length': 6.90715667311412, 'pattern_counts': {'":': 0, '<': 66, '<?xml version=': 0, '>': 65, 'https://': 0, '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': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '633632', 'license': 'MIT', 'n_tokens_mistral': 1545, 'n_tokens_neox': 1467, 'n_words': 288, 'path': 'oe_mpro_ifp.ipynb', 'repo_name': 'PatWalters/interaction_fingerprints', 'size': '4087'}