Source code for molpher.examples.basics

"""
Module with example code from the tutorial.

"""

from molpher.core import ExplorationTree as ETree
from molpher.core.operations import *

# TODO: make some of the stuff from this script part of the test suite
from molpher.core.operations.callbacks import TraverseCallback


[docs]def main(): cocaine = 'CN1[C@H]2CC[C@@H]1[C@@H](C(=O)OC)[C@@H](OC(=O)c1ccccc1)C2' procaine = 'O=C(OCCN(CC)CC)c1ccc(N)cc1' tree = ETree.create(source=cocaine, target=procaine) # initialize a tree that searches for a path from cocaine to procaine # print the smiles of the source and target molecule print('Source: ', tree.params['source']) print('Target: ', tree.params['target']) # change selected parameters using a dictionary print(tree.params) tree.params = { 'non_producing_survive' : 2, 'weight_max' : 500.0 } print(tree.params) print('\n#Generating and Manipulating Morphs') print(tree.leaves) # show the current leaves of the tree (only the source so far) print(tree.leaves[0].smiles) tree.generateMorphs() # generate new morphs print(tree.candidates) print(len(tree.candidates)) print() # get the first morph in the candidate list candidate = tree.candidates[0] # print distance to target print(tree.candidates[0].dist_to_target) # set new distance to target candidate.dist_to_target = 0.5 # look in the list of candidates and print new distance print(tree.candidates[0].dist_to_target) print() # make a copy of our molecule candidate_copy = candidate.copy() # set a new distance for the copy and verify that the original was not affected print(candidate_copy.dist_to_target) candidate_copy.dist_to_target = 0.7 print(candidate_copy.dist_to_target) print(candidate.dist_to_target) print(tree.candidates[0].dist_to_target) print('\n#Sorting and Filtering Morphs') # sort the candidates in the tree according to their distance from target tree.sortMorphs() # show results print(tree.candidates_mask) print( [ (x.smiles, x.dist_to_target) for x in tree.candidates ] ) print() # print the current candidates mask (all positions are on by default) print(tree.candidates_mask) # accept only the first three morphs in the sorted list (those with the lowest distance to target) mask = [False for x in tree.candidates_mask] mask[0] = True mask[1] = True mask[2] = True # save the new mask to the tree tree.candidates_mask = mask # show results print(tree.candidates_mask) print( [ (x.smiles, x.dist_to_target) for idx,x in enumerate(tree.candidates) if tree.candidates_mask[idx] # get accepted molecules only ] ) print('\n#Extending and Pruning') # get the number of generations before print(tree.generation_count) tree.extend() # connect the accepted morphs to the tree as new leaves print( sorted( # grab the new leaves as a list sorted according to their distance from target [ (x.getSMILES(), x.getDistToTarget()) for x in tree.leaves ], key=lambda item : item[1] ) ) # get the number of generations after print(tree.generation_count) # check if a path was found print(tree.path_found) # run the pruning operation on the updated tree tree.prune() print('\n#Operations') class MyFilterMorphs(TreeOperation): """ A custom tree operation that accepts only the first three morphs (those with the lowest distance to target). """ def __call__(self): """ This method is called automatically by the tree. The tree this operation is being run on is accessible from `self.tree`. """ mask = [False for x in self.tree.candidates_mask] mask[0] = True mask[1] = True mask[2] = True self.tree.candidates_mask = mask tree = ETree.create(source=cocaine, target=procaine) # create the tree # this list of tree operations defines one iteration iteration = [ GenerateMorphsOper() , SortMorphsOper() , MyFilterMorphs() , ExtendTreeOper() , PruneTreeOper() ] # apply the operations in the list one by one for oper in iteration: tree.runOperation(oper) # observe the results print(tree.generation_count) print(tree.path_found) print( sorted( # grab the new leaves as a list sorted according to their distance from target [ (x.getSMILES(), x.getDistToTarget()) for x in tree.leaves ], key=lambda x : x[1] ) ) print('\n#Traversing the Tree') class MyCallback(TraverseCallback): """ This callback just prints some information about the molecules in the tree. """ def __call__(self, morph): """ Method called on each morph in the tree -- starting from root to leaves. """ if not morph.getParentSMILES(): print("# Root #") else: print('# Morph #') print('Parent:', morph.getParentSMILES()) print('SMILES: ', morph.getSMILES()) print('Descendents: ', morph.getDescendants()) callback = MyCallback() # initialize a callback traverse = TraverseOper(callback) # attach it to a tree traversal operation tree.runOperation(traverse) # run the operation print() def process(morph): """ Prints some information about the molecules in the tree. """ if not morph.getParentSMILES(): print("# Root #") else: print('# Morph #') print('Parent:', morph.getParentSMILES()) print('SMILES: ', morph.getSMILES()) print('Descendents: ', morph.getDescendants()) tree.traverse(process) # use the traverse method to run the callback function print('\n#Tree Snapshots') template_file = 'cocaine-procaine-template.xml' import os template_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), template_file) # create a tree from the template file tree = ETree.create(template_file) print(tree.params) # apply the tree operations for oper in iteration: tree.runOperation(oper) print( sorted( # grab the new leaves as a list sorted according to their distance from target [ (x.getSMILES(), x.getDistToTarget()) for x in tree.leaves ], key=lambda x : x[1] ) ) # save the tree in a snapshot file tree.save('snapshot.xml') new_tree = ETree.create('snapshot.xml') # create a new tree from the saved snapshot print(new_tree.params) print( sorted( # grab the leaves in the created tree (these should be the same as those in the original tree) [ (x.getSMILES(), x.getDistToTarget()) for x in new_tree.leaves ], key=lambda x : x[1] ) )
if __name__ == "__main__": exit(main())