Example #1
0
    def __init__(self, smiles):
        self.smiles = smiles
        self.mol = get_mol(smiles)

        #Stereo Generation
        mol = Chem.MolFromSmiles(smiles)
        self.smiles3D = Chem.MolToSmiles(mol, isomericSmiles=True)
        self.smiles2D = Chem.MolToSmiles(mol)
        self.stereo_cands = decode_stereo(self.smiles2D)

        cliques, edges = tree_decomp(self.mol)
        self.nodes = []
        root = 0
        for i, c in enumerate(cliques):
            cmol = get_clique_mol(self.mol, c)
            node = MolTreeNode(get_smiles(cmol), c)
            self.nodes.append(node)
            if min(c) == 0:
                root = i

        for x, y in edges:
            self.nodes[x].add_neighbor(self.nodes[y])
            self.nodes[y].add_neighbor(self.nodes[x])

        if root > 0:
            self.nodes[0], self.nodes[root] = self.nodes[root], self.nodes[0]

        for i, node in enumerate(self.nodes):
            node.nid = i + 1
            if len(node.neighbors) > 1:  #Leaf node mol is not marked
                set_atommap(node.mol, node.nid)
            node.is_leaf = (len(node.neighbors) == 1)
Example #2
0
    def _recover_node(self, i, original_mol):
        node = self.nodes_dict[i]

        clique = []
        clique.extend(node['clique'])
        if not node['is_leaf']:
            for cidx in node['clique']:
                original_mol.GetAtomWithIdx(cidx).SetAtomMapNum(node['nid'])

        for j in self.successors(i).numpy():
            nei_node = self.nodes_dict[j]
            clique.extend(nei_node['clique'])
            if nei_node['is_leaf']:
                continue
            for cidx in nei_node['clique']:

                if cidx not in node['clique'] or len(nei_node['clique']) == 1:
                    atom = original_mol.GetAtomWithIdx(cidx)
                    atom.SetAtomMapNum(nei_node['nid'])

        clique = list(set(clique))
        label_mol = get_clique_mol(original_mol, clique)
        node['label'] = Chem.MolToSmiles(
            Chem.MolFromSmiles(get_smiles(label_mol)))
        node['label_mol'] = get_mol(node['label'])

        for cidx in clique:
            original_mol.GetAtomWithIdx(cidx).SetAtomMapNum(0)

        return node['label']
Example #3
0
    def recover(self, original_mol):
        clique = []
        clique.extend(self.clique)
        if not self.is_leaf:
            for cidx in self.clique:
                original_mol.GetAtomWithIdx(cidx).SetAtomMapNum(self.nid)

        for nei_node in self.neighbors:
            clique.extend(nei_node.clique)
            if nei_node.is_leaf:  #Leaf node, no need to mark
                continue
            for cidx in nei_node.clique:
                #allow singleton node override the atom mapping
                if cidx not in self.clique or len(nei_node.clique) == 1:
                    atom = original_mol.GetAtomWithIdx(cidx)
                    atom.SetAtomMapNum(nei_node.nid)

        clique = list(set(clique))
        label_mol = get_clique_mol(original_mol, clique)
        self.label = Chem.MolToSmiles(Chem.MolFromSmiles(
            get_smiles(label_mol)))
        self.label_mol = get_mol(self.label)

        for cidx in clique:
            original_mol.GetAtomWithIdx(cidx).SetAtomMapNum(0)

        return self.label
Example #4
0
    def __init__(self, smiles):
        DGLGraph.__init__(self)
        self.nodes_dict = {}
        if smiles is None:
            return
        self.smiles = smiles
        self.mol = get_mol(smiles)

        mol = Chem.MolFromSmiles(smiles)
        self.smiles3D = Chem.MolToSmiles(mol, isomericSmiles=True)
        self.smiles2D = Chem.MolToSmiles(mol)
        self.stereo_cands = decode_stereo(self.smiles2D)

        cliques, edges = tree_decomp(self.mol)
        root = 0
        for i, c in enumerate(cliques):
            cmol = get_clique_mol(self.mol, c)
            csmiles = get_smiles(cmol)
            self.nodes_dict[i] = dict(
                smiles=csmiles,
                mol=get_mol(csmiles),
                clique=c,
            )
            if min(c) == 0:
                root = i
        self.add_nodes(len(cliques))

        if root > 0:
            for attr in self.nodes_dict[0]:
                self.nodes_dict[0][attr], self.nodes_dict[root][attr] = \
                        self.nodes_dict[root][attr], self.nodes_dict[0][attr]

        src = np.zeros((len(edges) * 2, ), dtype='int')
        dst = np.zeros((len(edges) * 2, ), dtype='int')
        for i, (_x, _y) in enumerate(edges):
            x = 0 if _x == root else root if _x == 0 else _x
            y = 0 if _y == root else root if _y == 0 else _y
            src[2 * i] = x
            dst[2 * i] = y
            src[2 * i + 1] = y
            dst[2 * i + 1] = x
        self.add_edges(src, dst)

        for i in self.nodes_dict:
            self.nodes_dict[i]['nid'] = i + 1
            if self.out_degree(i) > 1:
                set_atommap(self.nodes_dict[i]['mol'],
                            self.nodes_dict[i]['nid'])
            self.nodes_dict[i]['is_leaf'] = (self.out_degree(i) == 1)
Example #5
0
    def __init__(self, smiles):
        self.smiles = smiles
        self.mol = get_mol(smiles)

        # Stereo Generation
        mol = Chem.MolFromSmiles(smiles)
        self.smiles3D = Chem.MolToSmiles(mol, isomericSmiles=True)
        self.smiles2D = Chem.MolToSmiles(mol)
        self.stereo_cands = decode_stereo(self.smiles2D)

        self.node_pair2bond = {}

        cliques, edges = tree_decomp(self.mol)
        self.nodes = []
        root = 0
        for i, c in enumerate(cliques):
            cmol = get_clique_mol(self.mol, c)
            node = MolTreeNode(get_smiles(cmol), c)
            self.nodes.append(node)
            if min(c) == 0:
                root = i

        self.n_edges = 0
        self.n_virtual_edges = 0
        for x, y in edges:
            self.nodes[x].add_neighbor(self.nodes[y])
            self.nodes[y].add_neighbor(self.nodes[x])
            xy_bond = self.nodes[x].add_neighbor_bond(self.nodes[y], self.mol)
            yx_bond = self.nodes[y].add_neighbor_bond(self.nodes[x], self.mol)
            self.node_pair2bond[(x, y)] = xy_bond
            self.node_pair2bond[(y, x)] = yx_bond
            if isinstance(xy_bond, RDKitBond) or isinstance(
                    yx_bond, RDKitBond):
                self.n_virtual_edges += 1
            self.n_edges += 1

        # change
        if root > 0:
            self.nodes[0], self.nodes[root] = self.nodes[root], self.nodes[0]

        for i, node in enumerate(self.nodes):
            node.nid = i + 1
            if len(node.neighbors) > 1:  # Leaf node mol is not marked
                set_atommap(node.mol, node.nid)
            node.is_leaf = (len(node.neighbors) == 1)
Example #6
0
    def build_mol_tree(self):
        cliques = self.cliques
        graph = nx.DiGraph()

        for i, clique in enumerate(cliques):
            cmol = get_clique_mol(self.mol, clique)
            graph.add_node(i)
            graph.nodes[i]['label'] = get_smiles(cmol)
            graph.nodes[i]['clq'] = clique

        for edge in self.edges:
            inter_atoms = list(set(cliques[edge[0]]) & set(cliques[edge[1]]))

            graph.add_edge(edge[0], edge[1])
            graph.add_edge(edge[1], edge[0])
            graph[edge[0]][edge[1]]['anchor'] = inter_atoms
            graph[edge[1]][edge[0]]['anchor'] = inter_atoms

            if len(inter_atoms) == 1:
                graph[edge[0]][edge[1]]['label'] = cliques[edge[0]].index(
                    inter_atoms[0])
                graph[edge[1]][edge[0]]['label'] = cliques[edge[1]].index(
                    inter_atoms[0])
            elif len(inter_atoms) == 2:
                index1 = cliques[edge[0]].index(inter_atoms[0])
                index2 = cliques[edge[0]].index(inter_atoms[1])
                if index2 == len(cliques[edge[0]]) - 1:
                    index2 = -1
                graph[edge[0]][edge[1]]['label'] = max(index1, index2)

                index1 = cliques[edge[1]].index(inter_atoms[0])
                index2 = cliques[edge[1]].index(inter_atoms[1])
                if index2 == len(cliques[edge[1]]) - 1:
                    index2 = -1
                graph[edge[1]][edge[0]]['label'] = max(index1, index2)

        return graph
Example #7
0
    def recover(self, original_mol):
        """
        This method, given the original molecule, of which this node's cluster is a part of,
        reconstruct the molecular fragment, consisting of this particular cluster and all its neighbor clusters

        Args:
            original_mol: The original molecule, of which is cluster is a part of.
        """
        cluster = []
        cluster.extend(self.cluster)

        # atomMapNum is used as a cluster label
        # we set the atomMapNum for all the atoms belonging to a particular cluster,
        # to the cluster idx of that particular cluster

        # if this node is not a leaf node,
        # then for all the atoms of this cluster in the original molecule,
        # set the AtomMapNum to the id of this "cluster-node"
        if not self.is_leaf:
            for atom_idx in self.cluster:
                atom = original_mol.GetAtomWithIdx(atom_idx)
                atom.SetAtomMapNum(self.nid)

        # similarly, for all the neighbor nodes,
        # for all the atom of the "neighbor cluster" in the original molecule,
        # set the AtomMapNum to the id of these "neighbor cluster-nodes"
        for neighbor_node in self.neighbors:
            cluster.extend(neighbor_node.cluster)

            # # leaf node, no need to mark
            if neighbor_node.is_leaf:
                continue
            for atom_idx in neighbor_node.cluster:
                # allow singleton node override the atom mapping

                # if the atom is not in current node's cluster i.e. it is not a shared atom,
                # then set the AtomMapNum to node_id of neighbor node
                # or, if this atom corresponds to a singleton cluster, then allow this
                # atom to override current "cluster-node's" node_id
                if atom_idx not in self.cluster or len(
                        neighbor_node.cluster) == 1:
                    atom = original_mol.GetAtomWithIdx(atom_idx)
                    atom.SetAtomMapNum(neighbor_node.nid)

        # a mega-cluster, corresponding to combination of current node's and its neighbors' clusters
        mega_cluster = list(set(cluster))

        # obtain the molecular fragment corresponding to this mega-cluster
        label_mol = get_cluster_mol(original_mol, mega_cluster)

        # obtain the corresponding SMILES representation for this molecular fragment
        self.label = Chem.MolToSmiles(Chem.MolFromSmiles(
            get_smiles(label_mol)))

        # obtain the corresponding molecular representation from the SMILES representation
        self.label_mol = get_kekulized_mol_from_smiles(self.label)

        # reset atom mapping to 0 for all the atoms of the original molecule
        for atom_idx in mega_cluster:
            original_mol.GetAtomWithIdx(atom_idx).SetAtomMapNum(0)

        return self.label
Example #8
0
    def __init__(self, smiles):
        """
        The constructor for the MolJuncTree class.

        Args:
            smiles: SMILES representation of molecule

        Returns:
            MolJuncTree object for the corresponding molecule.

        """

        # SMILES representation for the molecule
        self.smiles = smiles

        # kekulized molecular representation
        self.mol = get_kekulized_mol_from_smiles(self.smiles)

        # obtain all stereoisomers for this molecule
        mol = Chem.MolFromSmiles(smiles)

        self.smiles2D = Chem.MolToSmiles(mol)

        # assert(self.smiles == self.smiles2D)

        self.smiles3D = Chem.MolToSmiles(mol, isomericSmiles=True)

        assert (self.smiles2D == self.smiles3D)

        # obtain list of SMILES representation of all stereoisomers of the molecule, encoding their 3D structure
        self.stereo_candidates = decode_stereo(self.smiles2D)

        # obtain the clusters in the molecule and the adjacency list for the junction tree
        clusters, edges = self.cluster_decomposition()

        # list for storing the nodes of the junction tree
        self.nodes = []

        # idx for denoting the root of the junction tree
        root = 0

        # construct the nodes for the junction tree
        for idx, cluster in enumerate(clusters):
            # obtain the molecular fragment corresponding to the cluster
            cluster_mol = get_cluster_mol(self.mol, cluster)

            # instantiate a MolTreeNode corresponding to this cluster
            node = MolJuncTreeNode(get_smiles(cluster_mol), cluster)

            # append the node to the created list of nodes
            self.nodes.append(node)

            # if the atom with atom_idx equal to 0, in present in this cluster,
            # then denote this particular cluster as the root of the junction tree
            if min(cluster) == 0:
                root = idx

        # for each of the nodes of the junction tree, add neighbors,
        # based on the adjacency list obtained from the tree decomposition process
        for cluster_idx_1, cluster_idx_2 in edges:
            self.nodes[cluster_idx_1].add_neighbor(self.nodes[cluster_idx_2])
            self.nodes[cluster_idx_2].add_neighbor(self.nodes[cluster_idx_1])

        # if the root node has a cluster idx greater than 0, then swap it with the node having cluster_idx = 0
        if root > 0:
            self.nodes[0], self.nodes[root] = self.nodes[root], self.nodes[0]

        # set node_ids / nids for all the nodes
        for idx, node in enumerate(self.nodes):
            node.nid = idx + 1

            # for each of the non-leaf nodes,
            # for the atoms of the corresponding cluster,
            # we set the atomMapNum of these atoms,
            # to the node_id / nid of that node / cluster

            # leaf nodes have only 1 neighbor
            if len(node.neighbors) > 1:
                set_atom_map(node.mol, node.nid)

            node.is_leaf = (len(node.neighbors) == 1)