<jupyter_start><jupyter_text>Encode reaction SMILES as drfp fingerprints<jupyter_code># Make sure drfp is installed on binder
!pip install drfp
import numpy as np
from matplotlib import pyplot as plt
from sklearn.decomposition import PCA
from drfp import DrfpEncoder<jupyter_output>Requirement already satisfied: drfp in /home/daenu/code/clean/drfp/src (0.2.2.post1.dev12+gf5a2160.d20210704)
Requirement already satisfied: numpy>=1.21.0 in /home/daenu/miniconda3/envs/drfp/lib/python3.7/site-packages (from drfp) (1.21.0)
Requirement already satisfied: click>=8.0.1 in /home/daenu/miniconda3/envs/drfp/lib/python3.7/site-packages (from drfp) (8.0.1)
Requirement already satisfied: importlib-metadata in /home/daenu/miniconda3/envs/drfp/lib/python3.7/site-packages (from drfp) (4.6.0)
Requirement already satisfied: zipp>=0.5 in /home/daenu/miniconda3/envs/drfp/lib/python3.7/site-packages (from importlib-metadata->drfp) (3.5.0)
Requirement already satisfied: typing-extensions>=3.6.4 in /home/daenu/miniconda3/envs/drfp/lib/python3.7/site-packages (from importlib-metadata->drfp) (3.7.4.3)<jupyter_text>Let's load some reaction SMILES provided in the example file `reaction_smiles.csv`.<jupyter_code>smiles = []
with open("reaction_smiles.csv", "r") as f:
    smiles = [line.strip() for line in f]

print(f"{len(smiles)} reaction SMILES loaded. Here's an example:\n{smiles[0]}")<jupyter_output>100 reaction SMILES loaded. Here's an example:
CO.O.O=C(NC(=S)Nc1nc(-c2ccccc2)cs1)c1ccccc1.[Na+].[OH-]>>NC(=S)Nc1nc(-c2ccccc2)cs1<jupyter_text>Now encode using the `DrfpEncoder`:<jupyter_code>fps, mapping = DrfpEncoder.encode(smiles, mapping=True, n_folded_length=128)
print(smiles[0])
print(np.nonzero(fps[0]))
print(smiles[2])
print(np.nonzero(fps[2]))<jupyter_output>CO.O.O=C(NC(=S)Nc1nc(-c2ccccc2)cs1)c1ccccc1.[Na+].[OH-]>>NC(=S)Nc1nc(-c2ccccc2)cs1
(array([  6,   7,   8,  13,  25,  29,  35,  37,  40,  41,  43,  50,  55,
        61,  63,  67,  68,  73,  77,  87,  90, 100, 105, 108, 112, 113,
       116, 125]),)
CC(C)(C)[O-].[K+].CCOC(=O)CCCCCBr.CS(C)=O.c1ccc2c3c([nH]c2c1)CCCC3>>CCOC(=O)CCCCCn1c2c(c3ccccc31)CCCC2
(array([  0,   3,   7,   9,  11,  13,  19,  28,  29,  37,  38,  39,  42,
        50,  53,  56,  57,  58,  62,  65,  66,  68,  72,  74,  79,  82,
        86,  87,  88,  92,  94,  95,  96,  98,  99, 103, 104, 105, 107,
       109, 110, 111, 112, 113, 114, 122, 125, 127]),)<jupyter_text>Let's have a look at the the n-grams generated from *all* encoded molecules:<jupyter_code>n_grams_per_bin = [len(value) for value in mapping.values()]
print(f"There are {sum(n_grams_per_bin)} unique molecular n-grams.")
plt.hist(n_grams_per_bin)<jupyter_output>There are 2610 unique molecular n-grams.<jupyter_text>As we have chosen a dimensionality of 128, we have a lot of collisions when hashing the n-grams. However, we have shown that this isn't that big of an issue for classification tasks (see paper). But let's see what changes with different dimensions.<jupyter_code>for d in [256, 512, 1024, 2048]:
    fps, mapping = DrfpEncoder.encode(smiles, mapping=True, n_folded_length=d)
    n_grams_per_bin = [len(value) for value in mapping.values()]
    plt.hist(n_grams_per_bin)
    plt.title(f"Bin occupation for d={d}")
    plt.show()<jupyter_output><empty_output><jupyter_text>You can see where this is going... Now let's look at a few molecular n-grams:<jupyter_code>ngrams = list(mapping[list(mapping.keys())[0]])
print(ngrams)
ngrams = list(mapping[list(mapping.keys())[1]])
print(ngrams)<jupyter_output>['[C](=[S])([NH][C]([cH3])=[O])[NH][c]([nH])[s]', '[C](=[O])([OH])[c]([cH][nH])[c]([cH2])[Cl]']
['[n]([cH2])([cH2])-[cH3]', '[C](=[O])([CH2][Br])[c]([cH][cH2])[cH][cH2]', '[S]=[C]([NH][CH3])[NH][cH3]']<jupyter_text>Next, let's do a quick PCA of the data to see whether there is a pattern in our data...<jupyter_code>pca = PCA(n_components=2)
X = pca.fit(fps).transform(fps)

plt.scatter(X[:,0], X[:,1], alpha=0.8)
plt.title("PCA of 100 drfp-encoded reactions")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.17398901647528706, 'fraction_numerical': 0.07788317523714429, 'mean_word_length': 5.2904238618524335, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '108425', 'license': 'MIT', 'n_tokens_mistral': 1873, 'n_tokens_neox': 1682, 'n_words': 357, 'path': 'notebooks/01_fingerprinting.ipynb', 'repo_name': 'reymond-group/drfp', 'size': '4006'}