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
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
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
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))
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
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
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
def mass_exact(self): return RDKit.mass_exact(self.mol_rdkit)
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)
def react_rdkit_(self, smarts): if smarts is not None: return RDKit.reaction_from_smarts(smarts)
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
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
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
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
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