def test_fwd_reaction(): mol1 = Molecule(smiles="CC(=O)O", sanitize=True) mol2 = Molecule(smiles="NC", sanitize=True) reaction = Reaction( mols=[mol1, mol2], smarts="[C:1](=[O:2])-[OD1].[N!H0:3]>>[C:1](=[O:2])[N:3]") products = reaction.apply() assert len(products) == 1 assert len(products[0]) == 1 assert products[0][0].smiles == "CNC(C)=O"
def get_actions(self, molecules): """ Get all the probable actions of a set of molecules, using the policy and given cutoffs :param molecules: the molecules to consider :type molecules: list of Molecule :return: the actions and the priors of those actions :rtype: tuple (list of Reaction, numpy.ndarray) """ possible_actions = [] priors = [] for mol in molecules: if mol in self._stock: continue all_transforms_prop = self._predict(mol) probable_transforms_idx = self._cutoff_predictions( all_transforms_prop) possible_moves = self._templates.iloc[probable_transforms_idx] probs = all_transforms_prop[probable_transforms_idx] priors.extend(probs) for idx, (move_index, move) in enumerate(possible_moves.iterrows()): metadata = dict(move) del metadata[self._config.template_column] metadata["policy_probability"] = float(probs[idx]) metadata["template_code"] = move_index possible_actions.append( Reaction(mol, move[self._config.template_column], metadata=metadata)) return possible_actions, priors
def from_dict(cls, dict_, tree, config, molecules, parent=None): """ Create a new node from a dictionary, i.e. deserialization :param dict_: the serialized node :type dict_: dict :param tree: the search tree :type tree: SearchTree :param config: settings of the tree search algorithm :type config: Configuration :param molecules: the deserialized molecules :type molecules: MoleculeDeserializer :param parent: the parent node :type parent: Node :return: a deserialized node :rtype: Node """ state = State.from_dict(dict_["state"], config, molecules) node = Node(state=state, owner=tree, config=config, parent=parent) node.is_expanded = dict_["is_expanded"] node.is_expandable = dict_["is_expandable"] node._children_values = dict_["children_values"] node._children_priors = dict_["children_priors"] node._children_visitations = dict_["children_visitations"] node._children_actions = [ Reaction(molecules[action["mol"]], action["smarts"], action["index"]) for action in dict_["children_actions"] ] node._children = [ Node.from_dict(child, tree, config, molecules, parent=node) if child else None for child in dict_["children"] ] return node
def _select_child(self, idx): reaction = self._children_actions[idx] if self._children[idx]: return self._children[idx] states = self._make_child_states(reaction) if not states: self._children_values[idx] = -1e6 return None children = [] for i, state in enumerate(states): child = Node(state=state, owner=self._tree, config=self._config, parent=self) children.append(child) # If there's more than one outcome, the lists need be expanded if i > 0: new_action = Reaction(reaction.mol, reaction.smarts, index=i, metadata=reaction.metadata) self._children_actions.append(new_action) self._children_priors.append(self._children_priors[idx]) self._children_values.append(self._children_values[idx]) self._children_visitations.append( self._children_visitations[idx]) self._children.append(child) else: self._children[idx] = child return np.random.choice(children)
def wrapper(mol): actions = { "CCCCOc1ccc(CC(=O)N(C)O)cc1": [ "([#8:4]-[N;H0;D3;+0:5](-[C;D1;H3:6])-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3])" ">>(Cl-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3]).([#8:4]-[NH;D2;+0:5]-[C;D1;H3:6])", "([C:2]-[CH2;D2;+0:1]-[O;H0;D2;+0:3]-[c:4])>>(Br-[CH2;D2;+0:1]-[C:2]).([OH;D1;+0:3]-[c:4])", "([C:4]-[N;H0;D3;+0:5](-[C:6])-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3])>>" "(O-[C;H0;D3;+0:1](-[C:2])=[O;D1;H0:3]).([C:4]-[NH;D2;+0:5]-[C:6])", ] } action1, action2, action3 = actions[mol.smiles] action_list = [ Reaction(mol, action1), Reaction(mol, action2), Reaction(mol, action3), ] prior_list = [0.7, 0.5, 0.3] return action_list, prior_list
def setup_graphviz_graph(): mol1 = TreeMolecule(smiles="CCCO", parent=None) reaction = Reaction(mol=mol1, smarts="") graph = image.GraphvizReactionGraph() graph.add_molecule(mol1, "green") graph.add_reaction(reaction) graph.add_edge(mol1, reaction) return graph
def _sample_library(library: pd.DataFrame, config: Config, sampler_func: Callable) -> _DfGenerator: for _, row in library.iterrows(): mols = create_reactants_molecules(row.reactants) try: ref_mol = Molecule(smiles=row.products, sanitize=True) except MoleculeException: yield None continue new_product = None for template_row in sampler_func(row): if row.template_hash == template_row.template_hash: continue smarts_fwd = reverse_template(template_row.retro_template) try: new_product = Reaction(mols=mols, smarts=smarts_fwd).apply()[0][0] except (ValueError, IndexError): continue if new_product.basic_compare(ref_mol): continue break # If we have reached here, we have found a match that fits all criteria if not new_product: yield None continue # pylint: disable=undefined-loop-variable yield _new_dataframe( row, config, reaction_hash=[reaction_hash(row.reactants, new_product)], products=[new_product.smiles], classification=[""], retro_template=[template_row.retro_template], template_hash=[template_row.template_hash], selectivity=[0], outcomes=[1], template_code=[template_row.template_code], )
def _apply_forward_reaction(template_row: pd.Series, config: Config) -> Optional[pd.DataFrame]: smarts_fwd = reverse_template(template_row.retro_template) mols = create_reactants_molecules(template_row.reactants) try: ref_mol = Molecule(smiles=template_row.products, sanitize=True) except MoleculeException as err: raise _ReactionException( f"reaction {template_row.reaction_hash} failed with msg {str(err)}" ) try: products = Reaction(mols=mols, smarts=smarts_fwd).apply() except ValueError as err: raise _ReactionException( f"reaction {template_row.reaction_hash} failed with msg {str(err)}" ) new_products = { product[0] for product in products if product[0] != ref_mol } if not new_products: return None correct_products = { product[0] for product in products if product[0].basic_compare(ref_mol) } if not correct_products: raise _ReactionException( f"reaction {template_row.reaction_hash} failed to produce correct product" ) return _new_dataframe( template_row, config, nrows=len(new_products), reaction_hash=[ reaction_hash(template_row.reactants, product) for product in new_products ], products=[product.smiles for product in new_products], )
def setup_complete_tree(fresh_tree, mocker, mock_stock): tree = fresh_tree state1 = mocker.MagicMock() state1.mols = [ TreeMolecule( parent=None, transform=0, smiles="CN1CCC(C(=O)c2cccc(NC(=O)c3ccc(F)cc3)c2F)CC1", ) ] state1.in_stock_list = [False] state1.score = 0.049 state1.is_solved = False node1 = mocker.MagicMock() node1.state = state1 node1.parent = None node1.is_expanded = True action1 = ( "([C:2]-[CH;D3;+0:1](-[C:3])-[C;H0;D3;+0:4](=[O;H0;D1;+0:6])-[c:5])" ">>(Cl-[CH;D3;+0:1](-[C:2])-[C:3]).(N#[C;H0;D2;+0:4]-[c:5]).([OH2;D0;+0:6])" ) reaction1 = Reaction(state1.mols[0], action1) reaction1.apply() node1.__getitem__.return_value = {"action": reaction1} node1.is_terminal.return_value = False tree.root = node1 state2 = mocker.MagicMock() state2.mols = [ TreeMolecule(parent=state1.mols[0], smiles=smiles) for smiles in ["CN1CCC(Cl)CC1", "N#Cc1cccc(NC(=O)c2ccc(F)cc2)c1F", "O"] ] state2.in_stock_list = [True, False, True] state2.score = 0.68 state2.is_solved = False node2 = mocker.MagicMock() node2.parent = node1 node2.is_expanded = True node2.state = state2 node1.promising_child.return_value = node2 node1.children.return_value = [node2] action2 = ( "([O;D1;H0:2]=[C;H0;D3;+0:1](-[c:3])-[NH;D2;+0:4]-[c:5])" ">>(Cl-[C;H0;D3;+0:1](=[O;D1;H0:2])-[c:3]).([NH2;D1;+0:4]-[c:5])") reaction2 = Reaction(state2.mols[1], action2) reaction2.apply() node2.__getitem__.return_value = {"action": reaction2} state3 = mocker.MagicMock() state3.mols = [ TreeMolecule(parent=state2.mols[1], smiles=smiles) for smiles in ["N#Cc1cccc(N)c1F", "O=C(Cl)c1ccc(F)cc1"] ] state3.in_stock_list = [True, True] state3.stock = mocker.MagicMock() state3.stock.__contains__.side_effect = [ False, True, False, True, True, True ] state3.score = 0.99 state3.is_solved = True node3 = mocker.MagicMock() node3.parent = node2 node3.state = state3 node2.promising_child.return_value = node3 node2.children.return_value = [node3] return tree, [node1, node2, node3]