def decode(self, matrix): frags, smiles = [], [] for m, adj in enumerate(matrix): # print('decode: ', m) emol = Chem.RWMol() esub = Chem.RWMol() try: for atom, curr, prev, bond, frag in adj: atom, curr, prev, bond, frag = int(atom), int(curr), int( prev), int(bond), int(frag) if atom == self.tk2ix['EOS']: continue if atom == self.tk2ix['GO']: continue if atom != self.tk2ix['*']: a = Chem.Atom(self.ix2nr[atom]) a.SetFormalCharge(self.ix2ch[atom]) emol.AddAtom(a) if frag != 0: esub.AddAtom(a) if bond != 0: b = Chem.BondType(bond) emol.AddBond(curr, prev, b) if frag != 0: esub.AddBond(curr, prev, b) Chem.SanitizeMol(emol) Chem.SanitizeMol(esub) except Exception as e: print(adj) # raise e frags.append(Chem.MolToSmiles(esub)) smiles.append(Chem.MolToSmiles(emol)) return frags, smiles
def assertBondStereoRoundTrips(self, fname): path = os.path.join(RDConfig.RDCodeDir, 'Chem', 'test_data', fname) mol = Chem.MolFromMolFile(path) refSmiles = mol.GetProp("_Name") self.assertTrue(len(refSmiles) > 0) self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), refSmiles) # now test Chem.DetectBondStereoChemistry more directly by constructing the molecule from scratch oldconf = mol.GetConformer(0) newconf = Chem.Conformer(mol.GetNumAtoms()) newmol = Chem.RWMol() for atm in mol.GetAtoms(): ratm = Chem.Atom(atm.GetAtomicNum()) ratm.SetFormalCharge(atm.GetFormalCharge()) newmol.AddAtom(ratm) atomidx = atm.GetIdx() pos = oldconf.GetAtomPosition(atomidx) newconf.SetAtomPosition(atomidx, pos) for bnd in mol.GetBonds(): newmol.AddBond(bnd.GetBeginAtomIdx(), bnd.GetEndAtomIdx(), Chem.BondType(bnd.GetBondType())) newmol.AddConformer(newconf) Chem.SanitizeMol(newmol) Chem.DetectBondStereoChemistry(newmol, newmol.GetConformer()) # these aren't necessary for this specific test case, but are for # a more general conversion routine, so would like to see them # tested eventually # Chem.AssignAtomChiralTagsFromStructure(newmol) # Chem.AssignStereochemistry(newmol) self.assertEqual(Chem.MolToSmiles(newmol, isomericSmiles=True), refSmiles)
def to_rdmol(plams_mol, sanitize=True): """ Translate a PLAMS molecule into an RDKit molecule type """ # Create rdkit molecule e = Chem.EditableMol(Chem.Mol()) for atom in plams_mol.atoms: a = Chem.Atom(atom.atnum) ch = atom.properties.charge if isinstance(ch, int): a.SetFormalCharge(ch) e.AddAtom(a) for bond in plams_mol.bonds: a1 = plams_mol.atoms.index(bond.atom1) a2 = plams_mol.atoms.index(bond.atom2) e.AddBond(a1, a2, Chem.BondType(bond.order)) rdmol = e.GetMol() if sanitize: Chem.SanitizeMol(rdmol) conf = Chem.Conformer() for a in range(len(plams_mol.atoms)): atom = plams_mol.atoms[a] p = Geometry.Point3D(atom._getx(), atom._gety(), atom._getz()) conf.SetAtomPosition(a, p) rdmol.AddConformer(conf) return rdmol
def _prevent_allene(self, mol: Chem.Mol) -> Chem.Mol: if not isinstance(mol, Chem.RWMol): mol = Chem.RWMol(mol) for atom in mol.GetAtoms(): if atom.GetAtomicNum() < 14: n = [] for bond in atom.GetBonds(): if bond.GetBondType().name in ('DOUBLE', 'TRIPLE'): n.append(bond) else: pass if len(n) > 2: #this is a mess! log.info(f'Allene issue: {n} double bonds on {atom.GetSymbol()} atom {atom.GetIdx()}!') for bond in n: bond.SetBondType(Chem.BondType().SINGLE) elif len(n) == 2: # downgrade the higher bonded one! others = [a for bond in n for a in (bond.GetBeginAtom(), bond.GetEndAtom()) if a.GetIdx() != atom.GetIdx()] others = sorted(others, key=lambda atom: sum([b.GetBondTypeAsDouble() for b in atom.GetBonds()])) log.info(f'Allene removed between {atom.GetIdx()} and {[a.GetIdx() for a in others]}') mol.GetBondBetweenAtoms(atom.GetIdx(), others[-1].GetIdx()).SetBondType(Chem.BondType.SINGLE) else: pass else: continue return mol
def to_rdmol(plams_mol, sanitize=True): """ Translate a PLAMS molecule into an RDKit molecule type. :parameter plams_mol: PLAMS molecule :type plams_mol: plams.Molecule :return: an RDKit molecule :rtype: rdkit.Chem.Mol """ if isinstance(plams_mol, Chem.Mol): return plams_mol # Create rdkit molecule e = Chem.EditableMol(Chem.Mol()) for atom in plams_mol.atoms: a = Chem.Atom(atom.atnum) if 'charge' in atom.properties: a.SetFormalCharge(atom.properties.charge) if 'pdb_info' in atom.properties: set_PDBresidueInfo(a, atom.properties.pdb_info) e.AddAtom(a) for bond in plams_mol.bonds: a1 = plams_mol.atoms.index(bond.atom1) a2 = plams_mol.atoms.index(bond.atom2) e.AddBond(a1, a2, Chem.BondType(bond.order)) rdmol = e.GetMol() if sanitize: Chem.SanitizeMol(rdmol) conf = Chem.Conformer() for a in range(len(plams_mol.atoms)): atom = plams_mol.atoms[a] p = Geometry.Point3D(atom._getx(), atom._gety(), atom._getz()) conf.SetAtomPosition(a, p) rdmol.AddConformer(conf) return rdmol
def getbondtype(self,bondtype): if bondtype.GetBondType().__str__() == 'SINGLE': return Chem.BondType().DOUBLE elif bondtype.GetBondType().__str__() == 'DOUBLE': return Chem.BondType().TRIPLE elif bondtype.GetBondType().__str__() == 'TRIPLE': return Chem.BondType().QUADRUPLE elif bondtype.GetBondType().__str__() == 'QUADRUPLE': return Chem.BondType().QUINTUPLE elif bondtype.GetBondType().__str__() == 'QUINTUPLE': raise ReactionQueryError('BondIncrease: Increasing bond order above quintuple bond is not supported') elif bondtype.GetBondType().__str__() == 'AROMATIC': raise ReactionQueryError('BondIncrease: Increasing bond order of aromatic bond is not supported') elif bondtype.GetBondType().__str__() == 'DATIVE': raise ReactionQueryError('BondIncrease: Increasing bond order of partial bond is not supported') else: raise ReactionQueryError("BondDecrease: Unsupported bond type:'"+bondtype.GetBondType().__str__()+"'")
def convertSMILES(self, atoms, bonds): """Convert atoms and bonds information to SMILES.""" m = Chem.RWMol(Chem.MolFromSmiles('')) d = {} for name, number in zip(self.atomnames[atoms], atoms): d[number] = m.AddAtom(Chem.Atom(name)) for atom1, atom2, level in bonds: m.AddBond(d[atom1], d[atom2], Chem.BondType(level)) name = Chem.MolToSmiles(m) return name
def to_rdmol(plams_mol, sanitize=True, properties=True): """ Translate a PLAMS molecule into an RDKit molecule type. PLAMS |Molecule|, |Atom| or |Bond| properties are pickled if they are neither booleans, floats, integers, floats nor strings, the resulting property names are appended with '_pickled'. :parameter plams_mol: A PLAMS molecule :parameter bool sanitize: Kekulize, check valencies, set aromaticity, conjugation and hybridization :parameter bool properties: If all |Molecule|, |Atom| and |Bond| properties should be converted from PLAMS to RDKit format. :type plams_mol: |Molecule| :return: an RDKit molecule :rtype: rdkit.Chem.Mol """ if isinstance(plams_mol, Chem.Mol): return plams_mol # Create rdkit molecule e = Chem.EditableMol(Chem.Mol()) for atom in plams_mol.atoms: a = Chem.Atom(atom.atnum) if 'charge' in atom.properties: a.SetFormalCharge(atom.properties.charge) if properties: if 'pdb_info' in atom.properties: set_PDBresidueInfo(a, atom.properties.pdb_info) for prop in atom.properties: if prop != 'charge' or prop != 'pdb_info': prop_to_rdmol(atom, a, prop) e.AddAtom(a) for bond in plams_mol.bonds: a1 = plams_mol.atoms.index(bond.atom1) a2 = plams_mol.atoms.index(bond.atom2) e.AddBond(a1, a2, Chem.BondType(bond.order)) rdmol = e.GetMol() if properties: for pl_bond, rd_bond in zip(plams_mol.bonds, rdmol.GetBonds()): for prop in pl_bond.properties: prop_to_rdmol(pl_bond, rd_bond, prop) for prop in plams_mol.properties: prop_to_rdmol(plams_mol, rdmol, prop) if sanitize: Chem.SanitizeMol(rdmol) conf = Chem.Conformer() for a in range(len(plams_mol.atoms)): atom = plams_mol.atoms[a] p = Geometry.Point3D(atom._getx(), atom._gety(), atom._getz()) conf.SetAtomPosition(a, p) rdmol.AddConformer(conf) return rdmol
def to_rdmol(plams_mol, sanitize=True, properties=True, assignChirality=False): """ Translate a PLAMS molecule into an RDKit molecule type. PLAMS |Molecule|, |Atom| or |Bond| properties are pickled if they are neither booleans, floats, integers, floats nor strings, the resulting property names are appended with '_pickled'. :parameter plams_mol: A PLAMS molecule :parameter bool sanitize: Kekulize, check valencies, set aromaticity, conjugation and hybridization :parameter bool properties: If all |Molecule|, |Atom| and |Bond| properties should be converted from PLAMS to RDKit format. :parameter bool assignChirality: Assign R/S and cis/trans information, insofar as this was not yet present in the PLAMS molecule. :type plams_mol: |Molecule| :return: an RDKit molecule :rtype: rdkit.Chem.Mol """ if isinstance(plams_mol, Chem.Mol): return plams_mol # Create rdkit molecule e = Chem.EditableMol(Chem.Mol()) # Add atoms and assign properties to the RDKit atom if *properties* = True for pl_atom in plams_mol.atoms: rd_atom = Chem.Atom(pl_atom.atnum) if 'charge' in pl_atom.properties: rd_atom.SetFormalCharge(pl_atom.properties.charge) if properties: if 'pdb_info' in pl_atom.properties: set_PDBresidueInfo(rd_atom, pl_atom.properties.pdb_info) for prop in pl_atom.properties: if prop not in ('charge', 'pdb_info', 'stereo'): prop_to_rdmol(pl_atom, rd_atom, prop) # Check for R/S information if pl_atom.properties.stereo: stereo = pl_atom.properties.stereo.lower() if stereo == 'counter-clockwise': rd_atom.SetChiralTag( Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW) elif stereo == 'clockwise': rd_atom.SetChiralTag(Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CW) e.AddAtom(rd_atom) # Mapping of PLAMS bond orders to RDKit bond types: def plams_to_rd_bonds(bo): if bo > 1.4 and bo < 1.6: return 12 # bond type for aromatic bond else: return int(bo) # Add bonds to the RDKit molecule for bond in plams_mol.bonds: a1 = plams_mol.atoms.index(bond.atom1) a2 = plams_mol.atoms.index(bond.atom2) e.AddBond(a1, a2, Chem.BondType(plams_to_rd_bonds(bond.order))) rdmol = e.GetMol() # Check for cis/trans information for pl_bond, rd_bond in zip(plams_mol.bonds, rdmol.GetBonds()): if pl_bond.properties.stereo: stereo = pl_bond.properties.stereo.lower() if stereo == 'e' or stereo == 'trans': rd_bond.SetStereo(Chem.rdchem.BondStereo.STEREOE) elif stereo == 'z' or stereo == 'cis': rd_bond.SetStereo(Chem.rdchem.BondStereo.STEREOZ) elif stereo == 'up': rd_bond.SetBondDir(Chem.rdchem.BondDir.ENDUPRIGHT) elif stereo == 'down': rd_bond.SetBondDir(Chem.rdchem.BondDir.ENDDOWNRIGHT) # Assign properties to RDKit molecule and bonds if *properties* = True if properties: for prop in plams_mol.properties: prop_to_rdmol(plams_mol, rdmol, prop) for pl_bond, rd_bond in zip(plams_mol.bonds, rdmol.GetBonds()): for prop in pl_bond.properties: if prop != 'stereo': prop_to_rdmol(pl_bond, rd_bond, prop) if sanitize: Chem.SanitizeMol(rdmol) conf = Chem.Conformer() for i, atom in enumerate(plams_mol.atoms): xyz = Geometry.Point3D(atom._getx(), atom._gety(), atom._getz()) conf.SetAtomPosition(i, xyz) rdmol.AddConformer(conf) # REB: Assign all stereochemistry, if it wasn't already there if assignChirality: Chem.rdmolops.AssignAtomChiralTagsFromStructure( rdmol, confId=conf.GetId(), replaceExistingTags=False) try: Chem.AssignStereochemistryFrom3D(rdmol, confId=conf.GetId(), replaceExistingTags=False) except AttributeError: pass return rdmol