def test0Conformers(self) : """Test the conformer data structure""" mol = Chem.MolFromSmiles("CC") conf = Chem.Conformer(2) conf.SetAtomPosition(0, (-0.5, 0.0, 0.0)) conf.SetAtomPosition(1, (1.0, 0.0, 0.0)) conf.SetId(0) cid = mol.AddConformer(conf) self.assertTrue(cid == 0) conf2 = mol.GetConformer(0) self.assertTrue(conf2.GetId() == cid) pt1 = conf2.GetAtomPosition(0) self.assertTrue(ptEq(pt1, Point3D(-0.5, 0.0, 0.0))) pt2 = conf2.GetAtomPosition(1) self.assertTrue(ptEq(pt2, Point3D(1.0, 0.0, 0.0))) #changing conf should not change conf2 - related to issue 217 conf.SetAtomPosition(1, Point3D(2.0, 0.0, 0.0)) pt2 = conf2.GetAtomPosition(1) self.assertTrue(feq(pt2[0], 1.0)) conf = Chem.Conformer(2) conf.SetAtomPosition(0, Point3D(-0.5, 0.0, 0.0)) conf.SetAtomPosition(1, Point3D(1.0, 0.0, 0.0)) conf.SetId(2) cid = mol.AddConformer(conf, 0) self.assertTrue(cid == 2) conf3 = mol.GetConformer(2)
def test0AddHds(self) : mol = Chem.MolFromSmiles("CC") conf = Chem.Conformer(1) conf.SetAtomPosition(0, Point3D(-0.5, 0.0, 0.0)) conf.SetAtomPosition(1, Point3D(1.0, 0.0, 0.0)) cid = mol.AddConformer(conf) conf2 = mol.GetConformer() self.assertTrue(conf2.GetNumAtoms() == 2) nmol = Chem.AddHs(mol, 0,1) conf3 = nmol.GetConformer() self.assertTrue(conf3.GetNumAtoms() == 8) self.assertTrue(conf2.GetNumAtoms() == 2) targetCoords = [[-0.5, 0.0, 0.0], [1.0, 0.0, 0.0], [-0.8667, 0.0, 1.03709], [-0.8667, 0.8981, -0.5185], [-0.8667, -0.8981, -0.5185], [1.3667, 0.0, -1.0371], [1.36667, 0.8981, 0.5185], [1.36667, -0.8981, 0.5185]] for i in range(8) : pt = conf3.GetAtomPosition(i) self.assertTrue(ptEq(pt, Point3D(*tuple(targetCoords[i]))))
def test1Basics(self): fs = [ FreeChemicalFeature('Aromatic', 'Foo', Point3D(0, 0, 0)), FreeChemicalFeature('Acceptor', 'Foo', Point3D(2, 0, 0)), FreeChemicalFeature('Acceptor', 'Foo', Point3D(2.1, 0, 0)) ] aFmp = FeatMaps.FeatMapParams() aFmp.radius = 2.0 bFmp = FeatMaps.FeatMapParams() bFmp.radius = 1.0 fmps = {'Aromatic': aFmp, 'Acceptor': bFmp} fmap = FeatMaps.FeatMap(params=fmps) fmap.AddFeature(fs[0], 1.0) fmap.AddFeature(fs[1], 1.0) fmap.AddFeature(fs[2], 2.0) fmap.AddFeature(fs[2], 2.0) self.assertTrue(fmap.GetNumFeatures() == 4) self.assertTrue(len(fmap.GetFeatures()) == 4) fmap.DropFeature(3) self.assertTrue(fmap.GetNumFeatures() == 3) self.assertTrue(len(fmap.GetFeatures()) == 3) f = fmap.GetFeature(0) self.assertTrue(f.GetFamily() == 'Aromatic') self.assertTrue(feq(f.weight, 1.0)) f = fmap.GetFeature(1) self.assertTrue(f.GetFamily() == 'Acceptor') self.assertTrue(feq(f.weight, 1.0)) f = fmap.GetFeature(2) self.assertTrue(f.GetFamily() == 'Acceptor') self.assertTrue(feq(f.weight, 2.0))
def write_frame(host_coords, host_mol, guest_coords, guest_mol, guest_name, outdir, step, stage): if not os.path.exists(os.path.join(outdir, guest_name)): os.mkdir(os.path.join(outdir, guest_name)) host_frame = host_mol.GetConformer() for i in range(host_mol.GetNumAtoms()): x, y, z = host_coords[i] host_frame.SetAtomPosition(i, Point3D(x, y, z)) conf_id = host_mol.AddConformer(host_frame) writer = PDBWriter( os.path.join( outdir, guest_name, f"{guest_name}_{stage}_{step}_host.pdb", )) writer.write(host_mol, conf_id) writer.close() host_mol.RemoveConformer(conf_id) guest_frame = guest_mol.GetConformer() for i in range(guest_mol.GetNumAtoms()): x, y, z = guest_coords[i] guest_frame.SetAtomPosition(i, Point3D(x, y, z)) conf_id = guest_mol.AddConformer(guest_frame) guest_mol.SetProp("_Name", f"{guest_name}_{stage}_{step}_guest") writer = SDWriter( os.path.join( outdir, guest_name, f"{guest_name}_{stage}_{step}_guest.sdf", )) writer.write(guest_mol, conf_id) writer.close() guest_mol.RemoveConformer(conf_id)
def test5ScoreFeats(self): aFmp = FeatMaps.FeatMapParams() bFmp = FeatMaps.FeatMapParams() fmps = {'Aromatic': aFmp, 'Acceptor': bFmp} fmap = FeatMaps.FeatMap(params=fmps) fs = [ FreeChemicalFeature('Aromatic', 'Foo', Point3D(0, 0, 0)), FreeChemicalFeature('Acceptor', 'Foo', Point3D(2, 0, 0)), FreeChemicalFeature('Acceptor', 'Foo', Point3D(2.1, 0, 0)) ] fmap.AddFeature(fs[0], 1.1) fmap.AddFeature(fs[1], 1.1) fmap.AddFeature(fs[2], 2.1) l1 = fmap._loopOverMatchingFeats( FreeChemicalFeature('Aromatic', '', Point3D(0, 0, 0))) l1 = list(l1) self.assertTrue(len(l1) == 1) self.assertTrue(l1[0][0] == 0) self.assertTrue(l1[0][1].GetFamily() == 'Aromatic') l1 = fmap._loopOverMatchingFeats( FreeChemicalFeature('Acceptor', '', Point3D(0, 0, 0))) l1 = list(l1) self.assertTrue(len(l1) == 2) self.assertTrue(l1[0][0] == 1) self.assertTrue(l1[0][1].GetFamily() == 'Acceptor') self.assertTrue(l1[1][0] == 2) self.assertTrue(l1[1][1].GetFamily() == 'Acceptor')
def test4FeatFeatScoreBox(self): aFmp = FeatMaps.FeatMapParams() aFmp.radius = 2.0 aFmp.featProfile = FeatMaps.FeatMapParams.FeatProfile.Box fmps = {'Aromatic': aFmp} fmap = FeatMaps.FeatMap(params=fmps) fs = [FreeChemicalFeature('Aromatic', 'Foo', Point3D(0, 0, 0))] fmap.AddFeature(fs[0], 1.1) self.assertTrue(len(fmap.GetFeatures()) == 1) sc = fmap.GetFeatFeatScore( fmap.GetFeature(0), FreeChemicalFeature('Aromatic', '', Point3D(1, 0, 0))) self.assertTrue(feq(sc, 1.1)) sc = fmap.GetFeatFeatScore( fmap.GetFeature(0), FreeChemicalFeature('Aromatic', '', Point3D(1.5, 0, 0))) self.assertTrue(feq(sc, 1.1)) sc = fmap.GetFeatFeatScore( fmap.GetFeature(0), FreeChemicalFeature('Aromatic', '', Point3D(0, 0, 0))) self.assertTrue(feq(sc, 1.1)) sc = fmap.GetFeatFeatScore( fmap.GetFeature(0), FreeChemicalFeature('Aromatic', '', Point3D(2.1, 0, 0))) self.assertTrue(feq(sc, 0))
def test7ScoreFeats(self): aFmp = FeatMaps.FeatMapParams() aFmp.radius = 2.0 aFmp.featProfile = FeatMaps.FeatMapParams.FeatProfile.Box bFmp = FeatMaps.FeatMapParams() bFmp.radius = 1.0 bFmp.featProfile = FeatMaps.FeatMapParams.FeatProfile.Box fmps = {'Aromatic': aFmp, 'Acceptor': bFmp} fmap = FeatMaps.FeatMap(params=fmps) fs = [ FreeChemicalFeature('Aromatic', 'Foo', Point3D(0, 0, 0)), ] fmap.AddFeature(fs[0], 1.1) fs = [ FreeChemicalFeature('Aromatic', '', Point3D(0, 1, 0)), FreeChemicalFeature('Acceptor', '', Point3D(1.5, 0, 0)), ] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, 1.1)) msv = [-1] * 1 fsv = [-1] * 2 fsfmi = [-1] * 2 sc = fmap.ScoreFeats(fs, mapScoreVect=msv, featsScoreVect=fsv, featsToFeatMapIdx=fsfmi) self.assertTrue(feq(sc, 1.1)) self.assertTrue(feq(sum(msv), sc)) self.assertTrue(feq(sum(fsv), sc)) self.assertTrue(fsfmi == [[0], []]) fmap.scoreMode = FeatMaps.FeatMapScoreMode.Closest sc = fmap.ScoreFeats(fs, mapScoreVect=msv, featsScoreVect=fsv, featsToFeatMapIdx=fsfmi) self.assertTrue(feq(sc, 1.1)) self.assertTrue(feq(sum(msv), sc)) self.assertTrue(feq(sum(fsv), sc)) self.assertTrue(fsfmi == [[0], []]) fmap.scoreMode = FeatMaps.FeatMapScoreMode.Best sc = fmap.ScoreFeats(fs, mapScoreVect=msv, featsScoreVect=fsv, featsToFeatMapIdx=fsfmi) self.assertTrue(feq(sc, 1.1)) self.assertTrue(feq(sum(msv), sc)) self.assertTrue(feq(sum(fsv), sc)) self.assertTrue(fsfmi == [[0], []])
def get_ring_normal_vector(centroid, coordinates): """Returns a vector that is normal to the ring plane""" # A & B are two edges of the ring a = Point3D(*coordinates[0]) b = Point3D(*coordinates[1]) # vectors between centroid and these edges ca = centroid.DirectionVector(a) cb = centroid.DirectionVector(b) # cross product between these two vectors normal = ca.CrossProduct(cb) # cb.CrossProduct(ca) is the normal vector in the opposite direction return normal
def toRDKITmol(mol, protidx, sanitize=True, removeHs=False): # Taken from rdkit/Code/GraphMol/FileParsers/PDBParser.cpp conformer = Chem.Conformer(len(protidx)) conformer.Set3D(True) conformer.SetId(0) rdmol = Chem.RWMol() atomlist = [] for ii, i in enumerate(protidx): a = Chem.Atom(mol.element[i]) a.SetFormalCharge(int(mol.charge[i])) info = Chem.AtomPDBResidueInfo(atomName=mol.name[i], serialNumber=int(mol.serial[i]), altLoc=mol.altloc[i], residueName=mol.resname[i], residueNumber=int(mol.resid[i]), chainId=mol.chain[i], insertionCode=mol.insertion[i], occupancy=float(mol.occupancy[i]), tempFactor=float(mol.beta[i]), isHeteroAtom=mol.record[i] == 'HETATM') a.SetMonomerInfo(info) rdmol.AddAtom(a) atomlist.append(a) coor = [float(c) for c in mol.coords[i, :, mol.frame]] conformer.SetAtomPosition(ii, Point3D(coor[0], coor[1], coor[2])) # Correct the atom idx rdmol.AddConformer(conformer) # Here I diverge from the C++ parser because you cannot instantiate Chem.Bond objects in python # I also don't take into account double/triple bonds etc since I don't think we actually store them in Molecule for b in mol._getBonds(): if b[0] in protidx and b[1] in protidx: bond = rdmol.GetBondBetweenAtoms(int(b[0]), int(b[1])) if bond is None: rdmol.AddBond(int(np.where(protidx == b[0])[0]), int(np.where(protidx == b[1])[0]), Chem.BondType.SINGLE) # Proximitybonds I already did by using _getBonds which calls _guessBonds # TODO: Set PDB double bonds # Calculate explicit valence of atoms for a in atomlist: pass if sanitize: if removeHs: Chem.RemoveHs(rdmol) else: Chem.SanitizeMol(rdmol) else: rdmol.UpdatePropertyCache() # Set tetrahedral chirality from 3D co-ordinates Chem.AssignAtomChiralTagsFromStructure(rdmol) StandardPDBResidueChirality(rdmol) return rdmol
def get_orientation(self, xyz, rtol=0.15): """ get orientation, needs to check the tolerance """ from rdkit.Geometry import Point3D from rdkit.Chem import rdMolAlign, RemoveHs, rdmolfiles, rdMolTransforms mol = self.rdkit_mol(self.smile) conf0 = mol.GetConformer(0) conf1 = mol.GetConformer(1) conf2 = mol.GetConformer(2) angs = self.get_torsion_angles(xyz) xyz0 = self.set_torsion_angles(conf0, angs) #conf0 with aligned xyz1 = self.set_torsion_angles(conf0, angs, True) #conf0 with aligned for i in range(len(self.mol)): x0,y0,z0 = xyz0[i] x1,y1,z1 = xyz1[i] x,y,z = xyz[i] conf0.SetAtomPosition(i,Point3D(x0,y0,z0)) conf1.SetAtomPosition(i,Point3D(x,y,z)) conf2.SetAtomPosition(i,Point3D(x1,y1,z1)) mol = RemoveHs(mol) rmsd1, trans1 = rdMolAlign.GetAlignmentTransform(mol, mol, 1, 0) rmsd2, trans2 = rdMolAlign.GetAlignmentTransform(mol, mol, 1, 2) tol = rtol*mol.GetNumAtoms() #print(rmsd1, rmsd2) if rmsd1 < tol: trans = trans1[:3,:3].T r = Rotation.from_matrix(trans) return r.as_euler('zxy', degrees=True), rmsd1, False elif rmsd2 < tol: trans = trans2[:3,:3].T r = Rotation.from_matrix(trans) return r.as_euler('zxy', degrees=True), rmsd2, True else: print(rmsd1, rmsd2) #rdmolfiles.MolToXYZFile(mol, '1.xyz', 0) #rdmolfiles.MolToXYZFile(mol, '2.xyz', 1) #rdmolfiles.MolToXYZFile(mol, '3.xyz', 2) print(self.get_torsion_angles(xyz)) print(self.get_torsion_angles(xyz0)) print(self.get_torsion_angles(xyz1)) raise ValueError("Problem in conformer")
def test2FeatFeatScoreGauss(self): aFmp = FeatMaps.FeatMapParams() aFmp.radius = 2.0 fmps = {'Aromatic':aFmp} fmap = FeatMaps.FeatMap(params=fmps) fs = [FreeChemicalFeature('Aromatic','Foo',Point3D(0,0,0))] fmap.AddFeature(fs[0],1.0) self.failUnless(len(fmap.GetFeatures())==1) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(1,0,0))) self.failUnless(feq(sc,math.exp(-1))) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(1.5,0,0))) self.failUnless(feq(sc,math.exp(-2.25))) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(0,0,0))) self.failUnless(feq(sc,1.0)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(2.1,0,0))) self.failUnless(feq(sc,0)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Acceptor','',Point3D(1,0,0))) self.failUnless(feq(sc,0)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Acceptor','',Point3D(1,0,0)), typeMatch=False) self.failUnless(feq(sc,math.exp(-1))) self.failUnlessRaises(IndexError,lambda: fmap.GetFeatFeatScore(fmap.GetFeature(1),FreeChemicalFeature('Aromatic','',Point3D(0,0,0))))
def create_rdkit_mol(species, coords, bond_types, formal_charge=None, name=None, force_sanitize=True): """ Create a rdkit mol from scratch. Followed: https://sourceforge.net/p/rdkit/mailman/message/36474923/ Args: species (list): species str of each molecule coords (2D array): positions of atoms bond_types (dict): with bond indices (2 tuple) as key and bond type (e.g. Chem.rdchem.BondType.DOUBLE) as value formal_charge (list): formal charge of each atom name (str): name of the molecule force_sanitize (bool): whether to force the sanitization of molecule. If `True` and the sanitization fails, it generally throw an error and then stops. If `False`, will try to sanitize first, but if it fails, will proceed smoothly giving a warning message. Returns: rdkit Chem.Mol """ m = Chem.Mol() edm = Chem.EditableMol(m) conformer = Chem.Conformer(len(species)) for i, (s, c) in enumerate(zip(species, coords)): atom = Chem.Atom(s) atom.SetNoImplicit(True) if formal_charge is not None: cg = formal_charge[i] if cg is not None: atom.SetFormalCharge(cg) atom_idx = edm.AddAtom(atom) conformer.SetAtomPosition(atom_idx, Point3D(*c)) for b, t in bond_types.items(): edm.AddBond(b[0], b[1], t) m = edm.GetMol() if force_sanitize: Chem.SanitizeMol(m) else: try: Chem.SanitizeMol(m) except Exception as e: warnings.warn(f"Cannot sanitize molecule {name}, because {str(e)}") m.AddConformer(conformer, assignId=False) m.SetProp("_Name", str(name)) return m
def minimise_energy_all_confs(mol, models = None, epsilon = 4, allow_undefined_stereo = True, **kwargs ): from simtk import unit from simtk.openmm import LangevinIntegrator from simtk.openmm.app import Simulation, HBonds, NoCutoff from rdkit import Chem from rdkit.Geometry import Point3D import mlddec import copy import tqdm mol = Chem.AddHs(mol, addCoords = True) if models is None: models = mlddec.load_models(epsilon) charges = mlddec.get_charges(mol, models) from openforcefield.utils.toolkits import RDKitToolkitWrapper, ToolkitRegistry from openforcefield.topology import Molecule, Topology from openforcefield.typing.engines.smirnoff import ForceField # from openforcefield.typing.engines.smirnoff.forcefield import PME import parmed import numpy as np forcefield = ForceField(get_data_filename("modified_smirnoff99Frosst.offxml")) #FIXME better way of identifying file location tmp = copy.deepcopy(mol) tmp.RemoveAllConformers() #XXX workround for speed beacuse seemingly openforcefield records all conformer informations, which takes a long time. but I think this is a ill-practice molecule = Molecule.from_rdkit(tmp, allow_undefined_stereo = allow_undefined_stereo) molecule.partial_charges = unit.Quantity(np.array(charges), unit.elementary_charge) topology = Topology.from_molecules(molecule) openmm_system = forcefield.create_openmm_system(topology, charge_from_molecules= [molecule]) structure = parmed.openmm.topsystem.load_topology(topology.to_openmm(), openmm_system) system = structure.createSystem(nonbondedMethod=NoCutoff, nonbondedCutoff=1*unit.nanometer, constraints=HBonds) integrator = LangevinIntegrator(273*unit.kelvin, 1/unit.picosecond, 0.002*unit.picoseconds) simulation = Simulation(structure.topology, system, integrator) out_mol = copy.deepcopy(mol) for i in tqdm.tqdm(range(out_mol.GetNumConformers())): conf = mol.GetConformer(i) structure.coordinates = unit.Quantity(np.array([np.array(conf.GetAtomPosition(i)) for i in range(mol.GetNumAtoms())]), unit.angstroms) simulation.context.setPositions(structure.positions) simulation.minimizeEnergy() # simulation.step(1) coords = simulation.context.getState(getPositions = True).getPositions(asNumpy = True).value_in_unit(unit.angstrom) conf = out_mol.GetConformer(i) for j in range(out_mol.GetNumAtoms()): conf.SetAtomPosition(j, Point3D(*coords[j])) return out_mol
def positionMolecule(mol=Chem.rdchem.Mol(), centroid=SolutionInfo().dbCenter, rotation=SolutionInfo().dbRotation): conf = mol.GetConformer() for i in range(mol.GetNumAtoms()): x, y, z = rotation.dot(np.array(conf.GetAtomPosition(i)) - centroid) conf.SetAtomPosition(i, Point3D(x, y, z)) return
def repositionMolecule(mol=Chem.rdchem.Mol(), centroid=GaussianVolume().centroid, rotation=GaussianVolume().rotation): conf = mol.GetConformer() for i in range(mol.GetNumAtoms()): # Get coordinates x, y, z = rotation.dot(np.array(conf.GetAtomPosition(i))) + centroid conf.SetAtomPosition(i, Point3D(x, y, z)) return
def get_mol(self, ids=None): pmol = Chem.RWMol() all_coords = self.get_feature_coords(ids=ids) for item in all_coords: a = Chem.Atom(self.__feat_dict_mol[item[0]]) pmol.AddAtom(a) c = Conformer(len(all_coords)) for i, coords in enumerate(all_coords): c.SetAtomPosition(i, Point3D(*coords[1])) pmol.AddConformer(c, True) return pmol
def test3FeatFeatScoreTriangle(self): aFmp = FeatMaps.FeatMapParams() aFmp.width = 2.0 aFmp.radius = 3.0 aFmp.featProfile=FeatMaps.FeatMapParams.FeatProfile.Triangle fmps = {'Aromatic':aFmp} fmap = FeatMaps.FeatMap(params=fmps) fs = [FreeChemicalFeature('Aromatic','Foo',Point3D(0,0,0))] fmap.AddFeature(fs[0],1.0) self.failUnless(len(fmap.GetFeatures())==1) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(1,0,0))) self.failUnless(feq(sc,0.5)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(1.5,0,0))) self.failUnless(feq(sc,0.25)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(0,0,0))) self.failUnless(feq(sc,1.0)) sc = fmap.GetFeatFeatScore(fmap.GetFeature(0),FreeChemicalFeature('Aromatic','',Point3D(2.1,0,0))) self.failUnless(feq(sc,0))
def process_covalent(directory): link_atoms = {'SG': 16, 'O': 8, 'N': 7} print([x[0] for x in os.walk(directory)]) for f in [x[0] for x in os.walk(directory)]: print(str(f) + '/*_bound.pdb') print(glob.glob(str(f) + '/*_bound.pdb')) if glob.glob(str(f) + '/*_bound.pdb'): bound_pdb = glob.glob(str(f) + '/*_bound.pdb')[0] mol_file = glob.glob(str(f) + '/*.mol')[0] pdb = open(bound_pdb, 'r').readlines() link_info = write_lig_pdb(pdb) if link_info is not None: m2 = Chem.MolFromPDBFile('lig.pdb') for line in pdb: if line[13:17].strip() == link_info[1] and line[17:20] == link_info[2] and line[20:23].strip() == \ link_info[3] and line[23:27].strip() == link_info[4]: res_coords = [ line[31:39].strip(), line[39:47].strip(), line[47:55].strip() ] edmol = Chem.EditableMol(m2) new_mol = edmol.AddAtom(Chem.Atom(link_atoms[link_info[1]])) Chem.MolToPDBFile(edmol.GetMol(), 'edlig.pdb') edpdb = open('edlig.pdb', 'r').readlines() distances = {} for line in edpdb: if line.startswith('HETATM'): distances[get_3d_distance(res_coords, [ line[31:39].strip(), line[39:47].strip(), line[47:55].strip() ])] = line[7:11].strip() if [ line[31:39].strip(), line[39:47].strip(), line[47:55].strip() ] == ['0.000', '0.000', '0.000']: new_idx = line[7:11].strip() edmol.AddBond( int(distances[min(distances)]) - 1, int(new_idx) - 1, Chem.BondType.SINGLE) new_mol = edmol.GetMol() conf = new_mol.GetConformer() res_coords = tuple([float(i) for i in res_coords]) conf.SetAtomPosition( int(new_idx) - 1, Point3D(res_coords[0], res_coords[1], res_coords[2])) Chem.MolToMolFile(new_mol, mol_file)
def optimize(mol, args, program,log,dup_data,dup_data_idx): # if large system increase stack size if args.large_sys: os.environ['OMP_STACKSIZE'] = args.STACKSIZE # removing the Ba atom if NCI complexes if args.nci_complex: for atom in mol.GetAtoms(): if atom.GetSymbol() =='I': atom.SetAtomicNum(1) if args.metal_complex and not args.nodihedrals: set_metal_atomic_number(mol,args) elements = '' ase_metal = [] ase_metal_idx = [] for i,atom in enumerate(mol.GetAtoms()): if atom.GetIdx() in args.metal_idx: ase_metal.append(i) ase_metal_idx.append(atom.GetIdx()) elements += atom.GetSymbol() if os.path.splitext(args.input)[1] == '.cdx' or os.path.splitext(args.input)[1] == '.smi' or os.path.splitext(args.input)[1] == '.csv': args.charge = rules_get_charge(mol,args,log) dup_data.at[dup_data_idx, 'Overall charge'] = np.sum(args.charge) else: dup_data.at[dup_data_idx, 'Overall charge'] = args.charge_default cartesians = mol.GetConformers()[0].GetPositions() coordinates = torch.tensor([cartesians.tolist()], requires_grad=True, device=device) if program == 'ani': sqm_energy, coordinates = ani_calc(elements,cartesians,coordinates,args,log) elif program == 'xtb': sqm_energy, coordinates = xtb_calc(elements,cartesians,coordinates,args,log,ase_metal,ase_metal_idx) else: log.write('program not defined!') energy, cartesians = sqm_energy, np.array(coordinates.tolist()[0]) # update coordinates of mol object for j in range(mol.GetNumAtoms()): [x,y,z] = cartesians[j] mol.GetConformer().SetAtomPosition(j,Point3D(x,y,z)) return mol, energy
def get_center(self, xyz): """ get the molecular center for a transformed xyz """ if self.smile is None: return np.mean(xyz, axis=0) else: # from rdkit from rdkit.Geometry import Point3D from rdkit.Chem import rdMolTransforms as rdmt conf1 = self.rdkit_mol(self.smile).GetConformer(0) for i in range(conf1.GetNumAtoms()): x, y, z = xyz[i] conf1.SetAtomPosition(i, Point3D(x,y,z)) pt = rdmt.ComputeCentroid(conf1) return np.array([pt.x, pt.y, pt.z])
def test1BasicsRepeated(self): txt = self.paramTxt + """ BeginPoints family=Acceptor pos=(0.7, 0.0, 0.0) weight=1.0 family=Acceptor pos=(1.0, 0.0, 0.0) weight=1.0 family=Acceptor pos=(1.2, 0.0, 0.0) weight=1.0 family=Acceptor pos=(1.3, 0.0, 0.0) weight=1.0 family=Acceptor pos=(4.0, 0.0, 0.0) weight=1.0 EndPoints """ self.p.SetData(txt) fm1 = self.p.Parse() self.assertTrue(fm1.GetNumFeatures() == 5) self.assertTrue( FeatMapUtils.MergeFeatPoints(fm1, FeatMapUtils.MergeMetric.Distance)) self.assertTrue(fm1.GetNumFeatures() == 4) self.assertTrue(pteq(fm1.GetFeature(0).GetPos(), Point3D(0.7, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(1).GetPos(), Point3D(1.0, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(2).GetPos(), Point3D(1.25, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(3).GetPos(), Point3D(4.0, 0, 0))) self.assertTrue( FeatMapUtils.MergeFeatPoints(fm1, FeatMapUtils.MergeMetric.Distance)) self.assertTrue(fm1.GetNumFeatures() == 3) self.assertTrue(pteq(fm1.GetFeature(0).GetPos(), Point3D(0.7, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(1).GetPos(), Point3D(1.125, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(2).GetPos(), Point3D(4.0, 0, 0))) self.assertTrue( FeatMapUtils.MergeFeatPoints(fm1, FeatMapUtils.MergeMetric.Distance)) self.assertTrue(fm1.GetNumFeatures() == 2) self.assertTrue(pteq( fm1.GetFeature(0).GetPos(), Point3D(0.9125, 0, 0))) self.assertTrue(pteq(fm1.GetFeature(1).GetPos(), Point3D(4.0, 0, 0)))
def test4ConfTuple(self): smi = 'c1ccccc1' m = Chem.MolFromSmiles(smi) for i in range(10): addConf(m) confs = m.GetConformers() self.assertTrue(len(confs) == 10) for conf in confs: for i in range(6): pt = conf.GetAtomPosition(i) self.assertTrue(ptEq(pt, Point3D(0.0, 0.0, 0.0))) m.RemoveAllConformers() self.assertTrue(m.GetNumConformers() == 0) confs = m.GetConformers() self.assertTrue(confs == ())
def get_torsion_angles(self, xyz): """ get the torsion angles """ from rdkit.Geometry import Point3D from rdkit.Chem import rdMolTransforms as rdmt mol = self.rdkit_mol(self.smile) conf = mol.GetConformer(0) for i in range(len(self.mol)): x,y,z = xyz[i] conf.SetAtomPosition(i,Point3D(x,y,z)) angs = [] for torsion in self.torsionlist: (i, j, k, l) = torsion angs.append(rdmt.GetDihedralDeg(conf, i, j, k, l)) return angs
def get_principle_axes(self, xyz): """ get the principle axis for a rotated xyz """ if self.smile is None: Inertia = get_inertia_tensor(xyz) _, matrix = np.linalg.eigh(Inertia) return matrix else: from rdkit.Geometry import Point3D from rdkit.Chem import rdMolTransforms as rdmt conf1 = self.rdkit_mol(self.smile).GetConformer(0) for i in range(len(self.mol)): x,y,z = xyz[i] conf1.SetAtomPosition(i,Point3D(x,y,z)) return rdmt.ComputePrincipalAxesAndMoments(conf1)
def get_mol(self, ids=None): """ Returns RDKit Mol object of a pharmacophore where features are replaced with atoms :param ids: iterable with feature ids to be used :type ids: iterable (int) :return: RDKit RWMol """ pmol = Chem.RWMol() all_coords = self.get_feature_coords(ids=ids) for item in all_coords: a = Chem.Atom(self.__feat_dict_mol[item[0]]) pmol.AddAtom(a) c = Conformer(len(all_coords)) for i, coords in enumerate(all_coords): c.SetAtomPosition(i, Point3D(*coords[1])) pmol.AddConformer(c, True) return pmol
def test8ScoreFeatDirs(self): aFmp = FeatMaps.FeatMapParams() aFmp.radius = 2.0 aFmp.featProfile = FeatMaps.FeatMapParams.FeatProfile.Box fmps = {'Acceptor': aFmp} fmap = FeatMaps.FeatMap(params=fmps) fmap.dirScoreMode = FeatMaps.FeatDirScoreMode.DotFullRange fs = [ FreeChemicalFeature('Acceptor', 'Foo', Point3D(0, 0, 0)), ] fs[0].featDirs = [Point3D(0, 1, 0)] fmap.AddFeature(fs[0], 1.1) fs = [ FreeChemicalFeature('Acceptor', '', Point3D(1.0, 0, 0)), ] fs[0].featDirs = [Point3D(0, 1, 0)] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, 1.1)) fs[0].featDirs = [Point3D(0, -1, 0)] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, -1.1)) fs[0].featDirs = [Point3D(0, 0, 1)] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, 0.0)) fmap.dirScoreMode = FeatMaps.FeatDirScoreMode.DotPosRange fs[0].featDirs = [Point3D(0, -1, 0)] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, 0)) fs[0].featDirs = [Point3D(0, 1, 0)] sc = fmap.ScoreFeats(fs) self.assertTrue(feq(sc, 1.1))
def rotateMolecule(mol=Chem.rdchem.Mol(), rotor=SolutionInfo().rotor): rot = np.zeros(9).reshape(3, 3) r1 = rotor[1] * rotor[1] r2 = rotor[2] * rotor[2] r3 = rotor[3] * rotor[3] rot[0][0] = 1.0 - 2.0 * r2 - 2.0 * r3 rot[0][1] = 2.0 * (rotor[1] * rotor[2] - rotor[0] * rotor[3]) rot[0][2] = 2.0 * (rotor[1] * rotor[3] + rotor[0] * rotor[2]) rot[1][0] = 2.0 * (rotor[1] * rotor[2] + rotor[0] * rotor[3]) rot[1][1] = 1.0 - 2 * r3 - 2 * r1 rot[1][2] = 2.0 * (rotor[2] * rotor[3] - rotor[0] * rotor[1]) rot[2][0] = 2.0 * (rotor[1] * rotor[3] - rotor[0] * rotor[2]) rot[2][1] = 2.0 * (rotor[2] * rotor[3] + rotor[0] * rotor[1]) rot[2][2] = 1.0 - 2 * r2 - 2 * r1 conf = mol.GetConformer() for i in range(mol.GetNumAtoms()): x, y, z = rot.dot(np.array(conf.GetAtomPosition(i))) conf.SetAtomPosition(i, Point3D(x, y, z))
def generate_coordinates(self) -> None: """ Generate a 3D conformation for the Structure using RDKit. This may take a few attempts to set stereochemistry correctly. """ mol = self.to_mol() fixed_coords = {} for atom_index in self.fixed_atoms: atom = self.atoms[atom_index] coordinates = (atom.x, atom.y, atom.z) fixed_coords[atom_index] = Point3D(*coordinates) if self.use_etkdg: embed_parameters = AllChem.ETKDGv2() else: # noinspection PyArgumentList embed_parameters = AllChem.EmbedParameters() embed_parameters.useBasicKnowledge = True embed_parameters.ignoreSmoothingFailures = True embed_parameters.verbose = True if fixed_coords: embed_parameters.coordMap = fixed_coords AllChem.EmbedMolecule(mol, embed_parameters) centers_to_invert, previous_centers = set(), set() chiral_centers = Chem.FindMolChiralCenters(mol, True, True) chiral_centers = [x[0] for x in chiral_centers] n_cycles = 0 while n_cycles < 100: n_cycles += 1 # noinspection PyArgumentList conformer = mol.GetConformer() for (i, j, k, l), improper in self.improper_ics.items(): if k not in chiral_centers: continue measured_impr = AllChem.GetDihedralDeg(conformer, i, j, k, l) if ( (improper > 0 and measured_impr < 0) or (improper < 0 and measured_impr > 0) ): centers_to_invert.add(k) if not centers_to_invert: break # In case the chirality of one center is dependent upon another # This doesn't happen very often. if centers_to_invert == previous_centers: # Randomly pop one center and randomly add neighboring # chiral centers to the mix. center = centers_to_invert.pop() rd_atom = mol.GetAtomWithIdx(center) for neighbor in rd_atom.GetNeighbors(): neighbor_index = neighbor.GetIdx() if neighbor_index in chiral_centers: if np.random.random() >= 0.5: centers_to_invert.add(neighbor_index) if not centers_to_invert: centers_to_invert.add(center) for atom_index in centers_to_invert: rd_atom = mol.GetAtomWithIdx(atom_index) rd_atom.InvertChirality() previous_centers, centers_to_invert = centers_to_invert, set() AllChem.EmbedMolecule(mol, embed_parameters) else: raise ValueError("Unable to set stereochemistry correctly.") # noinspection PyArgumentList conformer = mol.GetConformer() for atom_index, atom in enumerate(self.atoms): position = conformer.GetAtomPosition(atom_index) atom.x = position.x atom.y = position.y atom.z = position.z
def mol_from_mae_file(mae_path): """ Creates a ``rdkit`` molecule from a ``.mae`` file. Parameters ---------- mol2_file : :class:`str` The full path of the ``.mae`` file from which an rdkit molecule should be instantiated. Returns ------- :class:`rdkit.Mol` An ``rdkit`` instance of the molecule held in `mae_file`. """ mol = rdkit.EditableMol(rdkit.Mol()) conf = rdkit.Conformer() with open(mae_path, 'r') as mae: content = re.split(r'[{}]', mae.read()) prev_block = deque([''], maxlen=1) for block in content: if 'm_atom[' in prev_block[0]: atom_block = block if 'm_bond[' in prev_block[0]: bond_block = block prev_block.append(block) labels, data_block, *_ = atom_block.split(':::') labels = [ label for label in labels.split('\n') if not label.isspace() and label != '' ] data_block = [ a.split() for a in data_block.split('\n') if not a.isspace() and a != '' ] for line in data_block: line = [word for word in line if word != '"'] if len(labels) != len(line): raise RuntimeError(('Number of labels does' ' not match number of columns' ' in .mae file.')) for label, data in zip(labels, line): if 'x_coord' in label: x = float(data) if 'y_coord' in label: y = float(data) if 'z_coord' in label: z = float(data) if 'atomic_number' in label: atom_num = int(data) atom_sym = periodic_table[atom_num] atom_coord = Point3D(x, y, z) atom_id = mol.AddAtom(rdkit.Atom(atom_sym)) conf.SetAtomPosition(atom_id, atom_coord) labels, data_block, *_ = bond_block.split(':::') labels = [ label for label in labels.split('\n') if not label.isspace() and label != '' ] data_block = [ a.split() for a in data_block.split('\n') if not a.isspace() and a != '' ] for line in data_block: if len(labels) != len(line): raise RuntimeError(('Number of labels does' ' not match number of ' 'columns in .mae file.')) for label, data in zip(labels, line): if 'from' in label: atom1 = int(data) - 1 if 'to' in label: atom2 = int(data) - 1 if 'order' in label: bond_order = str(int(data)) mol.AddBond(atom1, atom2, bond_dict[bond_order]) mol = mol.GetMol() mol.AddConformer(conf) return mol
def new_process_covalent(directory): for f in [x[0] for x in os.walk(directory)]: covalent = False print(str(f) + '/*_bound.pdb') print(glob.glob(str(f) + '/*_bound.pdb')) if glob.glob(str(f) + '/*_bound.pdb'): bound_pdb = glob.glob(str(f) + '/*_bound.pdb')[0] mol_file = glob.glob(str(f) + '/*.mol')[0] pdb = open(bound_pdb, 'r').readlines() for line in pdb: if 'LINK' in line: zero = line[13:27] one = line[43:57] if 'LIG' in zero: res = one covalent = True if 'LIG' in one: res = zero covalent = True if covalent: for line in pdb: if 'ATOM' in line and line[13:27]==res: res_x = float(line[31:39]) res_y = float(line[39:47]) res_z = float(line[47:55]) res_atom_sym = line.rsplit()[-1].rstrip() atom_sym_no = pd.read_csv('loader/atom_numbers.csv', index_col='symbol') res_atom_no = atom_sym_no.loc[res_atom_sym].number res_coords = [res_x, res_y, res_z] print(res_coords) atm = Chem.MolFromPDBBlock(line) atm_trans = atm.GetAtomWithIdx(0) mol = Chem.MolFromMolFile(mol_file) # edmol = Chem.EditableMol(mol) orig_pdb_block = Chem.MolToPDBBlock(mol) lig_block = '\n'.join([l for l in orig_pdb_block.split('\n') if 'COMPND' not in l]) lig_lines = [l for l in lig_block.split('\n') if 'HETATM' in l] j = 0 old_dist = 100 for line in lig_lines: j += 1 # print(line) if 'HETATM' in line: coords = [line[31:39].strip(), line[39:47].strip(), line[47:55].strip()] dist = get_3d_distance(coords, res_coords) if dist < old_dist: ind_to_add = j print(dist) old_dist = dist i = mol.GetNumAtoms() edmol = Chem.EditableMol(mol) edmol.AddAtom(atm_trans) edmol.AddBond(ind_to_add - 1, i, Chem.BondType.SINGLE) new_mol = edmol.GetMol() conf = new_mol.GetConformer() conf.SetAtomPosition(i, Point3D(res_coords[0], res_coords[1], res_coords[2])) try: Chem.MolToMolFile(new_mol, mol_file) except ValueError: Chem.MolToMolFile(new_mol, mol_file, kekulize=False)