예제 #1
0
def test_make_reaction_from_smiles():
    smiles = "CCCCOc1ccc(CC(=O)N(C)O)cc1>>CCCCOc1ccc(CC(=O)Cl)cc1.CNO"

    rxn = RetroReaction.from_reaction_smiles(smiles, smarts="")

    assert rxn.mol.smiles == "CCCCOc1ccc(CC(=O)N(C)O)cc1"
    assert len(rxn.reactants[0]) == 2
    assert rxn.reactants[0][0].smiles == "CCCCOc1ccc(CC(=O)Cl)cc1"
    assert rxn.reactants[0][1].smiles == "CNO"
예제 #2
0
 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 = [
         RetroReaction(mol, action1, metadata={"dummy": 1}),
         RetroReaction(mol, action2, metadata={"dummy": 2}),
         RetroReaction(mol, action3, metadata={"dummy": 3}),
     ]
     prior_list = [0.7, 0.5, 0.3]
     return action_list, prior_list
예제 #3
0
def setup_graphviz_graph():
    mol1 = TreeMolecule(smiles="CCCO", parent=None)
    reaction = RetroReaction(mol=mol1, smarts="")
    graph = image.GraphvizReactionGraph()

    graph.add_molecule(mol1, "green")
    graph.add_reaction(reaction)
    graph.add_edge(mol1, reaction)
    return graph
예제 #4
0
def serialize_action(
    action: RetroReaction, molecule_store: MoleculeSerializer
) -> StrDict:
    """
    Serialize a retrosynthesis action

    :param action: the (re)action to serialize
    :param molecule_store: the molecule serialization object
    :return: the action as a dictionary
    """
    dict_ = action.to_dict()
    dict_["mol"] = molecule_store[dict_["mol"]]
    dict_["class"] = f"{action.__class__.__module__}.{action.__class__.__name__}"
    return dict_
예제 #5
0
 def __init__(self, dict_, config, molecules, tree):
     self.tree = tree
     self.config = config
     self._children = [
         AndOrNode(child, config, molecules, tree) for child in dict_["children"]
     ]
     if "reaction" in dict_:
         self._obj = RetroReaction(
             molecules[dict_["reaction"]["mol"]],
             dict_["reaction"]["smarts"],
             dict_["reaction"]["index"],
             dict_["reaction"].get("metadata", {}),
         )
         self._solved = all(child.prop["solved"] for child in self._children)
     else:
         self.tree._mol_nodes.append(self)
         self._obj = molecules[dict_["mol"]]
         self._solved = self._obj in self.config.stock
예제 #6
0
    def get_actions(
        self, molecules: Sequence[TreeMolecule]
    ) -> Tuple[List[RetroReaction], List[float]]:
        """
        Get all the probable actions of a set of molecules, using the selected policies and given cutoffs

        :param molecules: the molecules to consider
        :return: the actions and the priors of those actions
        :raises: PolicyException: if the policy isn't selected
        """
        if not self.selection:
            raise PolicyException("No expansion policy selected")

        possible_actions = []
        priors = []

        for mol in molecules:
            if mol in self._stock:
                continue

            for policy_key in self.selection:
                model = self[policy_key]["model"]
                templates = self[policy_key]["templates"]

                all_transforms_prop = self._predict(mol, model)
                probable_transforms_idx = self._cutoff_predictions(
                    all_transforms_prop)
                possible_moves = 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].round(4))
                    metadata["policy_probability_rank"] = idx
                    metadata["policy_name"] = policy_key
                    metadata["template_code"] = move_index
                    possible_actions.append(
                        RetroReaction(mol,
                                      move[self._config.template_column],
                                      metadata=metadata))
        return possible_actions, priors
예제 #7
0
    def from_dict(
        cls,
        dict_: StrDict,
        tree: SearchTree,
        config: Configuration,
        molecules: MoleculeDeserializer,
        parent: "Node" = None,
    ) -> "Node":
        """
        Create a new node from a dictionary, i.e. deserialization

        :param dict_: the serialized node
        :param tree: the search tree
        :param config: settings of the tree search algorithm
        :param molecules: the deserialized molecules
        :param parent: the parent node
        :return: a deserialized 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 = []
        for action in dict_["children_actions"]:
            mol = molecules.get_tree_molecules([action["mol"]])[0]
            node._children_actions.append(
                RetroReaction(
                    mol,
                    action["smarts"],
                    action["index"],
                    action.get("metadata", {}),
                )
            )

        node._children = [
            Node.from_dict(child, tree, config, molecules, parent=node)
            if child
            else None
            for child in dict_["children"]
        ]
        return node
예제 #8
0
    def get_actions(self, molecules):
        """
        Get all the probable actions of a set of molecules, using the selected policies 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 RetroReaction, numpy.ndarray)
        """
        possible_actions = []
        priors = []

        for mol in molecules:
            if mol in self._stock:
                continue

            for policy_key in self.selection:
                model = self[policy_key]["model"]
                templates = self[policy_key]["templates"]

                all_transforms_prop = self._predict(mol, model)
                probable_transforms_idx = self._cutoff_predictions(
                    all_transforms_prop)
                possible_moves = 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["policy_name"] = policy_key
                    metadata["template_code"] = move_index
                    possible_actions.append(
                        RetroReaction(mol,
                                      move[self._config.template_column],
                                      metadata=metadata))
        return possible_actions, priors
예제 #9
0
    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 = [
            RetroReaction(
                molecules[action["mol"]],
                action["smarts"],
                action["index"],
                action.get("metadata", {}),
            ) 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
예제 #10
0
def setup_graphviz_graph():
    mol1 = TreeMolecule(smiles="CCCO", parent=None)
    reaction = RetroReaction(mol=mol1, smarts="")

    return [mol1], [reaction], [(mol1, reaction)], ["green"]
예제 #11
0
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
    state1.max_transforms = state1.mols[0].transform
    node1 = mocker.MagicMock()
    node1.state = state1
    node1.parent = None
    node1.tree = tree
    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 = RetroReaction(state1.mols[0], action1)
    reaction1.apply()
    node1.__getitem__.return_value = {"action": reaction1}
    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.max_transforms = state2.mols[0].transform
    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
    node2.tree = tree
    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 = RetroReaction(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.max_transforms = state3.mols[0].transform
    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.tree = tree
    node3.state = state3
    node2.promising_child.return_value = node3
    node2.children.return_value = [node3]
    node3.children.return_value = []

    return tree, [node1, node2, node3]