<jupyter_start><jupyter_text>Applying SMIRKSifier to AlkEthOH1. Load molecules and reference SMIRKS patterns from ChemPer data2. Use ChemPer utitility functions to cluster fragments from reference SMIRKS3. Make SMIRKS with all possible decorators using `SMIRKSifier`4. Run 10 iterations of the `Reducer` to make more general SMIRKS patterns5. Print out and save SMIRKS patterns6. (optional) reformat SMIRKS for LaTeX table<jupyter_code># import chemper utils and SMIRKSifier

from chemper import chemper_utils as cutils
from chemper.mol_toolkits import mol_toolkit
from chemper.smirksify import SMIRKSifier, Reducer, print_smirks
from numpy import random
import copy
def parse_smarts_file(file_path, lab=''):
    full_file_path = cutils.get_data_path(file_path)
    f = open(full_file_path)
    lines = f.readlines()
    f.close()
    type_list = list()
    for idx, l in enumerate(lines):
        type_list.append(('%s%i' % (lab, idx), l.strip()))
    return type_list
def write_smarts_files(type_list, file_path):
    f = open(file_path)
    for lab, smirks in type_list:
        f.write('%s %s\n' % (smirks, lab))
    f.close()<jupyter_output><empty_output><jupyter_text>1. Load Molecules and reference SMIRKS patterns<jupyter_code># load molecules
training_mols = mol_toolkit.mols_from_mol2('AlkEthOH_filtered_tripos.mol2')

smarts_files = [
    ('angle', 'smarts_files/angle_smirks.smarts'),
    ('bond', 'smarts_files/bond_smirks.smarts'),
    ('proper', 'smarts_files/proper_torsion_smirks.smarts'),
    ('nonbond', 'smarts_files/nonbond_smirks.smarts'),
]<jupyter_output><empty_output><jupyter_text>2-4 cluster fragments and generate SMIRKS patterns<jupyter_code># when not in travis tests increase the number of interations
its = 800 # 1000
# Get clusters for each parameter type
# training_dict = dict()
maxruns = 10
for label, smarts_file in smarts_files:
    if label == 'angle' or label == 'bond' or label == 'proper':
        continue
    print('='*80)
    print(' '*20, label)
    print('='*80)
    
    # Use function defined above to parse the smarts file and get reference SMIRKS patterns
    type_list = parse_smarts_file(smarts_file, smarts_file[0])
    
    training_dict[label] = dict()
    
    # =====================================================================================
    # 2: use ChemPer utilities function to type molecules with reference SMIRKS
    # =====================================================================================
    # First we'll type the molecules with the entire list of SMIRKS patterns
    train_ref = cutils.get_typed_molecules(type_list, training_mols)
    
    # We would like to only keep the SMIRKS used in this molecule set for simplicity
    # The dictionary has the form 
    #    {mol_id: {(atom indices): parameter_id} }
    # get the parameters used in the set
    pids = {p for m, a in train_ref.items() for ai, p in a.items()}
    # Save the SMIRKS that match those parameters
    type_list = [t for t in type_list if t[0] in pids]
    
    # Use ChemPer utilities to cluster fragments using the shorter list of patterns
    # note - these are the same clusters as the complete list, we only removed the empty clusters
    test_ref = cutils.get_typed_molecules(type_list, test_mols)
    clusters = cutils.create_tuples_for_clusters(type_list, training_mols)
    
    training_dict[label]['output_smirks'] = dict()
    training_dict[label]['input_smirks'] = type_list
    training_dict[label]['training_clusters'] = clusters
    
    its = 1000
    runs = 10
    # =====================================================================================
    # 3: SMIRKSify the clusters extracting all possible decorators
    # =====================================================================================
    ifier = SMIRKSifier(training_mols, clusters, verbose=False)
    print('first')
    print_smirks(ifier.current_smirks)
    
    red = Reducer(ifier.current_smirks, training_mols, verbose=False)
    final_smirks = red.run()
    
    training_dict[label]['output_smirks'][runs] = final_smirks
    print(runs)
    print_smirks(final_smirks)

    # =====================================================================================
    # 4: Reduce the initial SMIRKS 10 times saving each run
    # =====================================================================================
    while runs < maxruns:
        runs += 1
        red = Reducer(ifier.current_smirks, training_mols, verbose=False)
        final_smirks = red.run()
        print(runs)
        print_smirks(final_smirks)

        training_dict[label]['output_smirks'][runs] = final_smirks
    
    training_dict[label]['its'] = its<jupyter_output>================================================================================
                     nonbond
================================================================================
first

 Label                | SMIRKS 
================================================================================
 zz_s1                | [#1H0X1x0!r+0A:1]-;!@[#6r4,#6r5,#6r6,#6r7,#6r8,#6r9;+0;H2;X4;x2;A](-;!@[#1H0X1x0!r+0A])(-;@[#6H1r4,#6H1r5,#6H1r6,#6H1r7,#6H1r8,#6H1r9,#6H2r4,#6H2r5,#6H2r6,#6H2r7,#6H2r8,#6H2r9;+0;X4;x2;A])-;@[#6H1r4,#6H1r5,#6H1r6,#6H1r7,#6H1r8,#6H1r9,#6H2r4,#6H2r5,#6H2r6,#6H2r7,#6H2r8,#6H2r9;+0;X4;x2;A] 
--------------------------------------------------------------------------------
 zz_s2                | [#1H0X1x0!r+0A:1]-;!@[#6H1r4,#6H1r5,#6H1r6,#6H1r7,#6H1r8,#6H1r9,#6H2r4,#6H2r5,#6H2r6,#6H2r7,#6H2r8,#6H2r9;+0;X4;x2;A](-[#1!rH0X1x0,#6H2X4r4x2,#6H2X4r5x2,#6H2X4r6x2,#6H2X4r7x2,#6H2X4r8x2,#6H2X4r9x2;+0;A])(-;@[#6H1r4,#6H1r5,#6H1r6,#6H1r7,#6H1r8,#6H2r4,#6H2r5,#6H2r6,#6H2r7,[...]<jupyter_text>5. Print and save SMIRKS patterns ChemPer's `smirksify` module has a function `print_smirks` which attempts to format a list of SMIRKS patterns and their arbitrary labels. In the current arbitrary format the automatically generated SMIRKS have the form `zz_[original label]`.<jupyter_code>for label, smirks_data in training_dict.items():
    print(label)
    print_smirks(smirks_data['input_smirks'])
    for run, smriks in smirks_data['output_smirks'].items():
        print(run)
        print_smirks(smriks)
import pickle
pickle.dump(training_dict, open('alkethoh_dict.p', 'wb'))<jupyter_output><empty_output><jupyter_text>6. Make LaTeX formatted tablesThis is mostly one long for loop which just reformats the lists printed above to make tables compatible with LaTeX.<jupyter_code>def process_smirks(smirks):
    new_smirks = smirks.replace('~', '$\\sim$')
    new_smirks = new_smirks.replace('#', '\#')
    return '\\texttt{%s}' % new_smirks
import pickle
d = pickle.load(open('alkethoh_dict.p', 'rb'))

lines = list()
for frag in ['bond', 'angle', 'proper', 'nonbond']:
    if frag == 'proper':
        frag_label = 'Proper Torsion'
    else:
        frag_label = frag.capitalize()
    lines.append('\\renewcommand{\\arraystretch}{1.2}\n')
    lines.append('\\begin{longtable}{>{\\baselineskip=10pt}p{.07\\textwidth} >{\\baselineskip=10pt}p{.45\\textwidth} >{\\baselineskip=10pt}p{.4\\textwidth}} \n')
    lines.append('\multicolumn{3}{c}{%s parameters in AlkEthOH} \\\\ \n' % frag_label)
    lines.append('\\hline \n')
    lines.append('\\textbf{Label} & \\textbf{Original} & \\textbf{Reductions} \\\\ \n')
    lines.append('\\hline \n')
    lines.append('\\endhead')

    for idx, input_smirks in enumerate(d[frag]['input_smirks']):
        for run, output_smirks_list in d[frag]['output_smirks'].items():
            if run == 1:
                label = '\\textbf{%s}' % input_smirks[0]
                ins = process_smirks(input_smirks[1])
                outs = process_smirks(output_smirks_list[idx][1])

            else:
                label = ''
                ins = ''
                outs = process_smirks(output_smirks_list[idx][1])

            lines.append('%s & %s & %s \\\\ \n' % (label, ins, outs))
        lines.append('\\hline \n')

    lines.append('\\caption{This table shows the \\texttt{SMIRKS} patterns for %s parameters from smirnoff99Frosst (original). Then we show results from ten different runs of \\texttt{Reducer}. The stochastic decorator removal leads to different \\texttt{SMIRKS} patterns for each reduction.}\n' % frag_label)
    lines.append('\\label{tab:%s_alkethoh}\n' % frag)
    lines.append('\\end{longtable}\n\n\n')
    
f = open('alkethoh_tables.tex', 'w')
f.writelines(lines)
f.close()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.21636256621542083, 'fraction_numerical': 0.032842848734549734, 'mean_word_length': 4.139745916515427, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, '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': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '230586', 'license': 'MIT', 'n_tokens_mistral': 3070, 'n_tokens_neox': 2861, 'n_words': 606, 'path': 'alkethoh/AlkEthOH_Smirkisification.ipynb', 'repo_name': 'MobleyLab/chemper_proteins', 'size': '8495'}