예제 #1
0
 def create_from_smiles(cls, sm):
     try:
         m_rdkit = RDKit.mol_from_smiles(sm)
         if m_rdkit:
             m_inchi_key = RDKit.mol_to_inchi_key(m_rdkit)
             m = Molecule(mol_rdkit=m_rdkit, inchi_key=m_inchi_key)
             sm_can = RDKit.mol_to_smiles(m_rdkit)
             if len(sm_can) < 255:
                 m.smiles_with_limit = sm_can
             m.save()
             return m
         else:
             raise Exception
     except:
         return False
예제 #2
0
 def save(self, *args, **kwargs):
     if self.id is not None:
         prev_status = Reaction.objects.get(id=self.id).status_code
     else:
         prev_status = Reaction.status.EDIT
     if self.status_code == Reaction.status.INIT:
         self.status_code = Reaction.status.EDIT
     if (self.status_code == Reaction.status.EDIT
             and prev_status != Reaction.status.VALID):
         try:
             cd = ChemDoodle()
             smarts = cd.json_to_react(self.chemdoodle_json)
             self.smarts = smarts
             react = RDKit.reaction_from_smarts(smarts)
             self.chemdoodle_json = cd.react_to_json(react)
             self.chemdoodle_json_error = None
             if self.ready():
                 self.status_code = Reaction.status.VALID
             else:
                 self.chemdoodle_json_error = "error with RDKit"
         except ChemDoodleJSONError as error:
             self.chemdoodle_json_error = error
         except:
             self.chemdoodle_json_error = "unexpected error"
     self.reactants_number = self.get_reactants_number()
     super(Reaction, self).save(*args, **kwargs)
     return self
예제 #3
0
 def find_from_smiles(cls, sm):
     # Find a molecule from smiles by using inchi_key
     try:
         filter_res = Molecule.objects.filter(smiles_with_limit=sm)
         if filter_res.count() > 0:
             return filter_res.first()
         filter_res = Molecule.objects.filter(smiles_with_limit =\
                         RDKit.mol_to_smiles(RDKit.mol_from_smiles(sm)))
         if filter_res.count() > 0:
             return filter_res.first()
         filter_res = Molecule.objects.filter(inchi_key = \
                         RDKit.mol_to_inchi_key(RDKit.mol_from_smiles(sm)))
         if filter_res.count() > 0:
             return filter_res.first()
         return False
     except:
         return False
예제 #4
0
    def json_to_mol(self, json_data):
        from base.models import Molecule

        mol_rdkit = self.json_to_rdkit(json_data)
        smiles = Chem.MolToSmiles(mol_rdkit)
        smiles = RDKit.mol_to_smiles(mol_rdkit)
        # return Molecule.load_from_rdkit(mol_rdkit)
        return Molecule.load_from_smiles(Chem.MolToSmiles(mol_rdkit))
예제 #5
0
 def ready(self):
     try:
         cd = ChemDoodle()
         self.chemdoodle_json = cd.react_to_json(
             RDKit.reaction_from_smarts(self.smarts))
         rx = self.react_rdkit()
         return rx.Validate() == (0, 0)
     except:
         return False
예제 #6
0
 def load_from_rdkit(cls, mol):
     # Return a Molecule instance corresponding to the rdkit mol in input
     # create it if not exist
     from rdkit import Chem
     try:
         Chem.SanitizeMol(mol)
         m_smiles = RDKit.mol_to_smiles(mol)
         m = Molecule.load_from_smiles(m_smiles)
         return m
     except:
         return False
예제 #7
0
 def load_smarts(self, smarts):
     try:
         cd = ChemDoodle()
         react = RDKit.reaction_from_smarts(smarts)
         self.smarts = smarts
         self.chemdoodle_json = cd.react_to_json(react)
         self.status_code = Reaction.status.VALID
     except:
         self.status_code = Reaction.status.EDIT
     self.save()
     return self
예제 #8
0
 def mass_exact(self):
     return RDKit.mass_exact(self.mol_rdkit)
예제 #9
0
 def smiles(self, kekulize=False):
     if (not kekulize) and (self.smiles_with_limit != ""):
         return self.smiles_with_limit
     else:
         return RDKit.mol_to_smiles(self.mol_rdkit, kekulize)
예제 #10
0
 def react_rdkit_(self, smarts):
     if smarts is not None:
         return RDKit.reaction_from_smarts(smarts)
예제 #11
0
 def create_from_smarts(cls, smarts, name, user, description=None):
     smarts = RDKit.reaction_to_smarts(RDKit.reaction_from_smarts(smarts))
     r = cls(name=name, user=user, description=description, smarts=smarts)
     r.save()
     return r
예제 #12
0
    def json_to_react(self, json_data):
        line_x = None
        has_mapping = False
        if 's' in json_data:
            for s in (json_data['s']):
                if s['t'] == 'Line':
                    if line_x is not None:
                        raise ChemDoodleJSONError('More than one arrow')
                    line_x = (s['x1'],s['x2'])
                    if line_x[0] > line_x[1]:
                        raise ChemDoodleJSONError('Line in wrong direction')
                elif  s['t'] == 'AtomMapping':
                    has_mapping = True
        if line_x is None:
            raise ChemDoodleJSONError('No arrow')
        mols = []
        if 'm' in json_data:
            mols = json_data['m']
        # if len(mols) < 2:
        #     raise ChemDoodleJSONError('Not enough mols')
        # if len(mols) > 3:
        #     raise ChemDoodleJSONError('Too many mols')
        reactants = []
        product = None
        for m in mols:
            xs = None
            for a in m['a']:
                if xs is None:
                    xs = (a['x'], a['x'])
                else:
                    xs = (min(a['x'], xs[0]), max(a['x'], xs[1]))
            if not False in (xs[i] < line_x[0] for i in range(2)):
                reactants.append(m)
            elif not False in (xs[i] > line_x[1] for i in range(2)):
                if product is not None:
                    raise ChemDoodleJSONError('Too many products')
                product = m
            else:
                raise ChemDoodleJSONError('Ambiguous molecule position')
        if product is None:
            raise ChemDoodleJSONError('No product')
        if len(reactants) == 0:
            raise ChemDoodleJSONError('No reactants')
        if len(reactants) > 2:
            raise ChemDoodleJSONError('too many reactants')

        if not has_mapping:
            raise ChemDoodleJSONError('Need at least one mapping')

        map = json_data['s']

        try:
            smarts = \
                '{0}>>{1}'.format(
                    '.'.join((
                        self.json_to_smarts( m, map=map, mol_type='reactant') \
                        for m in reactants
                    )),
                    self.json_to_smarts( product, map=map, mol_type='product')
                )
        except:
            raise ChemDoodleJSONError('Error while converting molecules')

        smarts = smarts.replace('=', '=,:')
        try:
            react = RDKit.reaction_from_smarts(smarts)
            Chem.rdChemReactions.ReactionToSmarts(react)
        except:
            raise ChemDoodleJSONError('Error in RDKit with smarts generated')
        return smarts
예제 #13
0
    def json_to_rdkit(self, json_data, map={}, mol_type='reactant'):

        m0 = Chem.MolFromSmarts('')
        mw = Chem.RWMol(m0)

        atoms_cd = {}
        query_atoms = []

        for atom in json_data['a']:
            atom_id = atom['i']
            # Query atoms
            if 'q' in atom:
                q = atom['q']
                v = q['as']['v']
                if 'a' in v:
                    smarts = '[*]'
                    a_defaut = 'C'
                else:
                    smarts = v
                    # Manage aromaticity
                    if 'A' in q:
                        if not q['A']['n']:
                            smarts = []
                        if q['A']['v']:
                            smarts = smarts + [a_.lower() for a_ in v ]
                    smarts = '[{0}]'.format(','.join([a_ for a_ in smarts ]))
                    a_defaut = v[0]
                query_atoms.append((atom_id,smarts))
                a = Chem.Atom(a_defaut)
            # Non-query atoms
            else:
                symbol = 'C' if 'l' not in atom else atom['l']
                a = Chem.Atom(symbol)
                if 'c' in atom:
                    a.SetFormalCharge(atom['c'])
            atoms_cd[atom_id] = mw.AddAtom(a)

        if not 'b' in json_data:
            json_data['b'] = []

        for bond in json_data['b']:
            bond_id = bond['i']
            if 'o' in bond:
                bond_type = self.bond_type(bond['o'])
            else:
                bond_type = self.bond_type(1)
            mw.AddBond(bond['b'], bond['e'],bond_type) - 1

        bonds_cd1 = {
            i: mw.GetBondBetweenAtoms(b_cd['b'],b_cd['e']).GetIdx()
            for i,b_cd in enumerate(json_data['b'])
        }

        bonds_cd = {
            '{0}-{1}'.format(b_cd['b'], b_cd['e']): i
            for i,b_cd in enumerate(json_data['b'])
        }

        atoms_rd = {v: k for k, v in atoms_cd.items()}
        bonds_rd = {v: k for k, v in bonds_cd.items()}

        def a_point(atom_rd):
            x, y = ( json_data['a'][atom_rd][d] for d in ['x','y'] )
            return Point( x,y )

        def mol_atom(idx):
            return mw.GetAtoms()[idx]

        ### Manage chirality

        for atom in mw.GetAtoms():
            if atom.GetSymbol() == 'C':
                s = []
                for b in atom.GetBonds():
                    id_1 = '{0}-{1}'.format(
                                        b.GetBeginAtomIdx(),
                                        b.GetEndAtomIdx() )
                    if id_1 in bonds_cd:
                        b_cd = json_data['b'][ bonds_cd[id_1] ]
                    else:
                        b_cd = json_data['b'][ bonds_cd['{1}-{0}'.format(
                                            b.GetBeginAtomIdx(),
                                            b.GetEndAtomIdx() )] ]
                    if 's' in b_cd:
                        s.append(b_cd['s'])
                    else:
                        s.append('')
                if len(s) == 4 and s.count('protruding')*s.count('recessed') == 1:
                    points = []
                    for i,b in enumerate(atom.GetBonds()):
                        if  b.GetBeginAtomIdx() != atom.GetIdx():
                            a = b.GetBeginAtomIdx()
                        else:
                            a = b.GetEndAtomIdx()

                        if s[i] == 'protruding':
                            z = 1
                        elif s[i] == 'recessed':
                            z = - 1
                        else:
                            z = 0
                        points.append( Point( [i for i in a_point(a)] + [z] ) )
                    int = Line( points[2].midpoint(points[3]), points[1] )\
                            .intersection(
                                Line( points[1].midpoint(points[2]), points[3] ) )[0]
                    N = CoordSys3D('N')
                    coords = [N.i,N.j,N.k]
                    vectors = []
                    for p in points:
                        v = Vector.zero
                        for v_ in [ n*coords[v] for v,n in enumerate(p-int) ]:
                            v += v_
                        vectors.append(v)
                    if vectors[1].cross(vectors[3]).dot(vectors[0]) > 0:
                        atom.SetChiralTag(Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW)
                    else:
                        atom.SetChiralTag(Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CW)

        ### Manage stereo

        for bond in mw.GetBonds():
            if bond.GetBondType() == Chem.rdchem.BondType.DOUBLE \
                and bond.GetBeginAtom().GetSymbol() == 'C' \
                and bond.GetEndAtom().GetSymbol() == 'C':
                carbons = [ bond.GetBeginAtomIdx(), bond.GetEndAtomIdx() ]
                # Check if stero can be applied
                if True in [ len(mol_atom(c).GetBonds()) > 1 for c in carbons ]:
                    sa = [ \
                            [b.GetBeginAtomIdx() \
                                if b.GetBeginAtomIdx() != c \
                                else b.GetEndAtomIdx()#,
                                for b in mol_atom(c).GetBonds() \
                                    if b.GetBondType() == Chem.rdchem.BondType.SINGLE ] \
                            for c in carbons ]
                    if not [] in sa:
                        sa = [ sa[i][0] for i in range(2) ]
                        bond.SetStereoAtoms (sa[0], sa[1])

                        if len( intersection(
                                Segment( a_point(sa[0]), a_point(sa[1]) ),
                                Line( a_point(carbons[0]), a_point(carbons[1]) )
                            )) > 0:
                            bond.SetStereo(Chem.rdchem.BondStereo.STEREOTRANS)
                        else:
                            bond.SetStereo(Chem.rdchem.BondStereo.STEREOCIS)

        # replace query_atoms
        if len(query_atoms) > 0:
            for id, smarts in query_atoms:
                m_a = Chem.MolFromSmarts(smarts)
                Chem.SanitizeMol(m_a)
                mw.ReplaceAtom(atoms_cd[id],m_a.GetAtoms()[0])

        # Map atoms
        i = 1
        for m in map:
            if m['t'] == 'AtomMapping':
                a_rd_id = None
                for a in ['a1', 'a2']:
                    if m[a] in atoms_cd:
                        a_rd_id = atoms_cd[ m[a] ]
                if a_rd_id is not None:
                    mw.GetAtoms()[a_rd_id].SetAtomMapNum(i)
                i += 1


        mol = mw.GetMol()
        RDKit.apply_aromaticity(mol)
        Chem.rdDepictor.Compute2DCoords(mol)

        return mol
예제 #14
0
    def json_to_react(self, json_data):
        line_x = None
        has_mapping = False
        if "s" in json_data:
            for s in json_data["s"]:
                if s["t"] == "Line":
                    if line_x is not None:
                        raise ChemDoodleJSONError("More than one arrow")
                    line_x = (s["x1"], s["x2"])
                    if line_x[0] > line_x[1]:
                        raise ChemDoodleJSONError("Line in wrong direction")
                elif s["t"] == "AtomMapping":
                    has_mapping = True
        if line_x is None:
            raise ChemDoodleJSONError("No arrow")
        mols = []
        if "m" in json_data:
            mols = json_data["m"]
        # if len(mols) < 2:
        #     raise ChemDoodleJSONError('Not enough mols')
        # if len(mols) > 3:
        #     raise ChemDoodleJSONError('Too many mols')
        reactants = []
        product = None
        for m in mols:
            xs = None
            for a in m["a"]:
                if xs is None:
                    xs = (a["x"], a["x"])
                else:
                    xs = (min(a["x"], xs[0]), max(a["x"], xs[1]))
            if not False in (xs[i] < line_x[0] for i in range(2)):
                reactants.append(m)
            elif not False in (xs[i] > line_x[1] for i in range(2)):
                if product is not None:
                    raise ChemDoodleJSONError("Too many products")
                product = m
            else:
                raise ChemDoodleJSONError("Ambiguous molecule position")
        if product is None:
            raise ChemDoodleJSONError("No product")
        if len(reactants) == 0:
            raise ChemDoodleJSONError("No reactants")
        if len(reactants) > 2:
            raise ChemDoodleJSONError("too many reactants")

        if not has_mapping:
            raise ChemDoodleJSONError("Need at least one mapping")

        map = json_data["s"]

        try:
            smarts = "{0}>>{1}".format(
                ".".join((self.json_to_smarts(m, map=map, mol_type="reactant")
                          for m in reactants)),
                self.json_to_smarts(product, map=map, mol_type="product"),
            )
        except:
            raise ChemDoodleJSONError("Error while converting molecules")

        smarts = smarts.replace("=", "=,:")
        try:
            react = RDKit.reaction_from_smarts(smarts)
            Chem.rdChemReactions.ReactionToSmarts(react)
        except:
            raise ChemDoodleJSONError("Error in RDKit with smarts generated")
        return smarts
예제 #15
0
    def json_to_rdkit(self, json_data, map={}, mol_type="reactant"):

        m0 = Chem.MolFromSmarts("")
        mw = Chem.RWMol(m0)

        atoms_cd = {}
        query_atoms = []

        for atom in json_data["a"]:
            atom_id = atom["i"]
            # Query atoms
            if "q" in atom:
                q = atom["q"]
                v = q["as"]["v"]
                if "a" in v:
                    smarts = "[*]"
                    a_defaut = "C"
                else:
                    smarts = v
                    # Manage aromaticity
                    if "A" in q:
                        if not q["A"]["n"]:
                            smarts = []
                        if q["A"]["v"]:
                            smarts = smarts + [a_.lower() for a_ in v]
                    smarts = "[{0}]".format(",".join([a_ for a_ in smarts]))
                    a_defaut = v[0]
                query_atoms.append((atom_id, smarts))
                a = Chem.Atom(a_defaut)
            # Non-query atoms
            else:
                symbol = "C" if "l" not in atom else atom["l"]
                a = Chem.Atom(symbol)
                if "c" in atom:
                    a.SetFormalCharge(atom["c"])
            atoms_cd[atom_id] = mw.AddAtom(a)

        if not "b" in json_data:
            json_data["b"] = []

        for bond in json_data["b"]:
            bond_id = bond["i"]
            if "o" in bond:
                bond_type = self.bond_type(bond["o"])
            else:
                bond_type = self.bond_type(1)
            mw.AddBond(bond["b"], bond["e"], bond_type) - 1

        bonds_cd1 = {
            i: mw.GetBondBetweenAtoms(b_cd["b"], b_cd["e"]).GetIdx()
            for i, b_cd in enumerate(json_data["b"])
        }

        bonds_cd = {
            "{0}-{1}".format(b_cd["b"], b_cd["e"]): i
            for i, b_cd in enumerate(json_data["b"])
        }

        atoms_rd = {v: k for k, v in atoms_cd.items()}
        bonds_rd = {v: k for k, v in bonds_cd.items()}

        def a_point(atom_rd):
            x, y = (json_data["a"][atom_rd][d] for d in ["x", "y"])
            return Point(x, y)

        def mol_atom(idx):
            return mw.GetAtoms()[idx]

        ### Manage chirality

        for atom in mw.GetAtoms():
            if atom.GetSymbol() == "C":
                s = []
                for b in atom.GetBonds():
                    id_1 = "{0}-{1}".format(b.GetBeginAtomIdx(),
                                            b.GetEndAtomIdx())
                    if id_1 in bonds_cd:
                        b_cd = json_data["b"][bonds_cd[id_1]]
                    else:
                        b_cd = json_data["b"][bonds_cd["{1}-{0}".format(
                            b.GetBeginAtomIdx(), b.GetEndAtomIdx())]]
                    if "s" in b_cd:
                        s.append(b_cd["s"])
                    else:
                        s.append("")
                if len(s) == 4 and s.count("protruding") * s.count(
                        "recessed") == 1:
                    points = []
                    for i, b in enumerate(atom.GetBonds()):
                        if b.GetBeginAtomIdx() != atom.GetIdx():
                            a = b.GetBeginAtomIdx()
                        else:
                            a = b.GetEndAtomIdx()

                        if s[i] == "protruding":
                            z = 1
                        elif s[i] == "recessed":
                            z = -1
                        else:
                            z = 0
                        points.append(Point([i for i in a_point(a)] + [z]))
                    int = Line(points[2].midpoint(points[3]),
                               points[1]).intersection(
                                   Line(points[1].midpoint(points[2]),
                                        points[3]))[0]
                    N = CoordSys3D("N")
                    coords = [N.i, N.j, N.k]
                    vectors = []
                    for p in points:
                        v = Vector.zero
                        for v_ in [
                                n * coords[v] for v, n in enumerate(p - int)
                        ]:
                            v += v_
                        vectors.append(v)
                    if vectors[1].cross(vectors[3]).dot(vectors[0]) > 0:
                        atom.SetChiralTag(
                            Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW)
                    else:
                        atom.SetChiralTag(
                            Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CW)

        ### Manage stereo

        for bond in mw.GetBonds():
            if (bond.GetBondType() == Chem.rdchem.BondType.DOUBLE
                    and bond.GetBeginAtom().GetSymbol() == "C"
                    and bond.GetEndAtom().GetSymbol() == "C"):
                carbons = [bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()]
                # Check if stero can be applied
                if True in [len(mol_atom(c).GetBonds()) > 1 for c in carbons]:
                    sa = [
                        [
                            b.GetBeginAtomIdx() if b.GetBeginAtomIdx() != c
                            else b.GetEndAtomIdx()  # ,
                            for b in mol_atom(c).GetBonds()
                            if b.GetBondType() == Chem.rdchem.BondType.SINGLE
                        ] for c in carbons
                    ]
                    if not [] in sa:
                        sa = [sa[i][0] for i in range(2)]
                        bond.SetStereoAtoms(sa[0], sa[1])

                        if (len(
                                intersection(
                                    Segment(a_point(sa[0]), a_point(sa[1])),
                                    Line(a_point(carbons[0]),
                                         a_point(carbons[1])),
                                )) > 0):
                            bond.SetStereo(Chem.rdchem.BondStereo.STEREOTRANS)
                        else:
                            bond.SetStereo(Chem.rdchem.BondStereo.STEREOCIS)

        # replace query_atoms
        if len(query_atoms) > 0:
            for id, smarts in query_atoms:
                m_a = Chem.MolFromSmarts(smarts)
                Chem.SanitizeMol(m_a)
                mw.ReplaceAtom(atoms_cd[id], m_a.GetAtoms()[0])

        # Map atoms
        i = 1
        for m in map:
            if m["t"] == "AtomMapping":
                a_rd_id = None
                for a in ["a1", "a2"]:
                    if m[a] in atoms_cd:
                        a_rd_id = atoms_cd[m[a]]
                if a_rd_id is not None:
                    mw.GetAtoms()[a_rd_id].SetAtomMapNum(i)
                i += 1

        mol = mw.GetMol()
        RDKit.apply_aromaticity(mol)
        Chem.rdDepictor.Compute2DCoords(mol)

        return mol