Esempio n. 1
0
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"
Esempio n. 2
0
    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
Esempio n. 3
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 = [
            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
Esempio n. 4
0
    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)
Esempio n. 5
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 = [
         Reaction(mol, action1),
         Reaction(mol, action2),
         Reaction(mol, action3),
     ]
     prior_list = [0.7, 0.5, 0.3]
     return action_list, prior_list
Esempio n. 6
0
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
Esempio n. 7
0
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],
        )
Esempio n. 8
0
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],
    )
Esempio n. 9
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
    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]