def testUFFTorsionConstraints(self): m = Chem.MolFromMolBlock(self.molB, True, False) conf = m.GetConformer() rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 15.0) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, 10.0, 20.0, 100.0) r = ff.Minimize() self.assertTrue(r == 0) dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertAlmostEqual(dihedral, 20, delta=0.1) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -30.0) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, 8.0, 100.0) r = ff.Minimize() self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertAlmostEqual(dihedral, -40, delta=0.1) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -10.0) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, -10.0, 8.0, 1.0e6) r = ff.Minimize(500) self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertAlmostEqual(dihedral, -10, delta=0.1)
def testUFFTorsionConstraints(self) : m = Chem.MolFromMolBlock(self.molB, True, False) conf = m.GetConformer() rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 50.0); ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, 10.0, 20.0, 1.0e5) r = ff.Minimize() self.assertTrue(r == 0) dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertTrue(int(dihedral) == 20) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -30.0); ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, -8.0, 1.0e5) r = ff.Minimize() self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertTrue(int(dihedral) == -40) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 30.0); ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, -10.0, -8.0, 1.0e5) r = ff.Minimize(1000) self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertTrue(int(dihedral) == -10)
def _get_child_states(self): child_states = [] if len(self.state[1]) < len(self._rotatable_bonds): mol = self.state[0] conf = mol.GetConformer() mol.AddConformer(conf, assignId=True) bond_to_rotate = self._rotatable_bonds[len(self.state[1])] theta = rdMolTransforms.GetDihedralDeg(conf, bond_to_rotate[0], bond_to_rotate[1], bond_to_rotate[2], bond_to_rotate[3]) for allowed_angle_value in self._allowed_angle_values: new_theta = theta + allowed_angle_value rdMolTransforms.SetDihedralDeg(conf, bond_to_rotate[0], bond_to_rotate[1], bond_to_rotate[2], bond_to_rotate[3], new_theta) mol.AddConformer(conf, assignId=True) mol.RemoveConformer(conf.GetId()) for i, conf in enumerate(mol.GetConformers()): theta = rdMolTransforms.GetDihedralDeg(conf, bond_to_rotate[0], bond_to_rotate[1], bond_to_rotate[2], bond_to_rotate[3]) child_mol = Chem.Mol(mol, False, conf.GetId()) child_states.append((child_mol, self.state[1] + [theta])) return child_states
def testMMFFTorsionConstraints(self): m = Chem.MolFromMolBlock(self.molB, True, False) conf = m.GetConformer() rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 15.0) mp = ChemicalForceFields.MMFFGetMoleculeProperties(m) ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp) self.assertTrue(ff) ff.MMFFAddTorsionConstraint(1, 3, 6, 8, False, 10.0, 20.0, 100.0) r = ff.Minimize() self.assertTrue(r == 0) dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertEquals(int(dihedral), 20) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -30.0) ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp) self.assertTrue(ff) ff.MMFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, 8.0, 100.0) r = ff.Minimize() self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertTrue(int(dihedral) == -40) rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -10.0) ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp) self.assertTrue(ff) ff.MMFFAddTorsionConstraint(1, 3, 6, 8, False, -10.0, 8.0, 100.0) r = ff.Minimize(1000) self.assertTrue(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.assertTrue(int(dihedral) == -10)
def testGetSetDihedralThroughTripleBond(self): file = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'MolTransforms', 'test_data', 'github1262_2.mol') m = Chem.MolFromMolFile(file, True, False) conf = m.GetConformer() rdmt.SetDihedralDeg(conf, 6, 1, 2, 9, 0.0) dihedral = rdmt.GetDihedralDeg(conf, 6, 1, 2, 9) self.assertAlmostEqual(dihedral, 0.0, 1) dist = rdmt.GetBondLength(conf, 6, 9) rdmt.SetDihedralDeg(conf, 6, 1, 2, 9, 120.0) dihedral = rdmt.GetDihedralDeg(conf, 6, 1, 2, 9) self.assertAlmostEqual(dihedral, 120.0, 1) dist2 = rdmt.GetBondLength(conf, 6, 7) self.assertAlmostEqual(dist, dist2, 1) rdmt.SetDihedralDeg(conf, 6, 1, 2, 9, 180.0) dihedral = rdmt.GetDihedralDeg(conf, 6, 1, 2, 9) self.assertAlmostEqual(dihedral, 180.0, 1) dist3 = rdmt.GetBondLength(conf, 6, 9) self.assertNotAlmostEqual(dist, dist3, 1) exceptionRaised = False try: rdmt.SetDihedralDeg(conf, 6, 0, 3, 9, 0.0) except ValueError: exceptionRaised = True self.assertTrue(exceptionRaised)
def get_dihedrals(self): """ Get dihedral angles """ raw_rot_bonds = self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[!#1]~[!$(*#*)&!D1]-!@[!$(*#*)&!D1]~[!#1]")) raw_rot_bonds += self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[O,S]-[#1]")) raw_rot_bonds += self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[NX3;H2]-[#1]")) bonds = [] rot_bonds = [] for k, i, j, l in raw_rot_bonds: if (i, j) not in bonds and ( j, i) not in bonds: # makes sure that dihedrals are unique bonds.append((i, j)) rot_bonds.append((k, i, j, l)) conf = self.molecule.GetConformer() angles = [] for k, i, j, l in rot_bonds: theta = rdMolTransforms.GetDihedralDeg(conf, k, i, j, l) # print k,i,j,l,theta angles.append([k, i, j, l, theta]) return angles
def get_dihedral(self, mol, atom1, atom2, atom3, atom4, units="radians"): """ It calculates the value of the dihedral angle in the specified units (default radians) Parameters ---------- molecule : an offpele.topology.Molecule The offpele's Molecule object atom1 : int Index of the first atom in the dihedral atom2 : int Index of the second atom in the dihedral atom3 : int Index of the third atom in the dihedral atom4 : int Index of the fourth atom in the dihedral units : str The units in which to calculate the angle (default is radians, can be radians or degrees) """ from rdkit.Chem import rdMolTransforms if units == "degrees": angle = rdMolTransforms.GetDihedralDeg( mol.rdkit_molecule.GetConformer(), atom1, atom2, atom3, atom4) else: angle = rdMolTransforms.GetDihedralRad( mol.rdkit_molecule.GetConformer(), atom1, atom2, atom3, atom4) return angle
def test_measure_dihedrals(acetone): """ Make sure we can correctly measure all dihedrals in the molecule. """ dihedral_values = acetone.measure_dihedrals() rdkit_mol = acetone.to_rdkit() for dihedral, value in dihedral_values.items(): assert (pytest.approx( rdMolTransforms.GetDihedralDeg(rdkit_mol.GetConformer(), *dihedral)) == value)
def testUFFTorsionConstraints(self): m = Chem.MolFromMolBlock(self.molB, True, False) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.failUnless(ff) conf = m.GetConformer() rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 60.0) ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, 30.0, 30.0, 1.0e5) r = ff.Minimize() self.failUnless(r == 0) dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.failUnless(int(dihedral) == 30) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.failUnless(ff) ff.UFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, 10.0, 1.0e5) r = ff.Minimize() self.failUnless(r == 0) conf = m.GetConformer() dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8) self.failUnless(int(dihedral) == 40)
def dihedral_strain(self, dihedral_SMARTS='', target=180, conformer=-1): """ Returns the difference between the average dihedral and target. The differences is a returned as a percent. Parameters ---------- dihedral_SMARTS : :class:`str` The SMARTS code for the dihedral of interest. target : :class:`float` Float representing the target value for the dihedral angle. conformer : :class:`int`, optional The id of the conformer to be used. Returns ------- :class:`float` The percent difference between the average dihedral in the molecule and the target value. """ match = rdkit.MolFromSmarts(dihedral_SMARTS) atoms_dihedral = self.mol.GetSubstructMatches(match) dihedral_info = [] if len(atoms_dihedral) > 0 and len(atoms_dihedral[0]) != 0: for atoms_group in atoms_dihedral: # Calculate the dihedral angle. dihedral_value = rdMolTransforms.GetDihedralDeg( self.mol.GetConformer(conformer), atoms_group[0], atoms_group[1], atoms_group[2], atoms_group[3]) # Check that the dihedral is calculated in the right # direction. if abs(dihedral_value) > 90: dihedral_value = abs(dihedral_value) else: dihedral_value = 180 - abs(dihedral_value) dihedral_info.append(dihedral_value) # Calculate the average dihedral value. avg_dihedral = np.mean([abs(x) for x in dihedral_info]) # Calculate the relative diff with the target dihedral # value. diff = (abs(target - avg_dihedral) / target) * 100 else: # If the molecule does not contain the bond, give 1% # strain. diff = 1 return diff
def testGetSetDihedral(self): file = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'MolTransforms', 'test_data', '3-cyclohexylpyridine.mol') m = Chem.MolFromMolFile(file, True, False) conf = m.GetConformer() dihedral = rdmt.GetDihedralDeg(conf, 0, 19, 21, 24) self.failUnlessAlmostEqual(dihedral, 176.05, 2) rdmt.SetDihedralDeg(conf, 8, 0, 19, 21, 65.0) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, 65.0, 1) rdmt.SetDihedralDeg(conf, 8, 0, 19, 21, -130.0) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -130.0, 1) rdmt.SetDihedralRad(conf, 21, 19, 0, 8, -2. / 3. * math.pi) dihedral = rdmt.GetDihedralRad(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -2. / 3. * math.pi, 1) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -120.0, 1)
def _select_next_move_randomly(self, state): mol = Chem.Mol(state[0]) # create a copy of the Mol conf = mol.GetConformer() bond_to_rotate = self._rotatable_bonds[len(state[1])] theta = rdMolTransforms.GetDihedralDeg(conf, bond_to_rotate[0], bond_to_rotate[1], bond_to_rotate[2], bond_to_rotate[3]) theta += np.random.choice(self._allowed_angle_values) rdMolTransforms.SetDihedralDeg(conf, bond_to_rotate[0], bond_to_rotate[1], bond_to_rotate[2], bond_to_rotate[3], theta) conformer_id = mol.AddConformer(conf, assignId=True) return Chem.Mol(mol, False, conformer_id), state[1] + [theta]
def GetTorsionDeg(self, torsion: list, ) -> float: """ Get the dihedral angle of the torsion in degrees. The torsion can be defined by any atoms in the molecule (not necessarily bonded atoms.) Args: torsion (list): A list of four atom indexes. Returns: float: The dihedral angle of the torsion. """ return rdMT.GetDihedralDeg(self._conf, *torsion)
def get_energies(self, resolution=30, get_thetas=False): """ It returns the energies of this energetic profile calculator. Parameters ---------- resolution : float The resolution, in degrees, that is applied when rotating the dihedral rotatable bond. Default is 30 degrees get_thetas : bool Whether to return thetas (dihedral angles) or not. Default is False Returns ------- dihedral_energies : a simtk.unit.Quantity object The array of energies represented with a simtk's Quantity object thetas : list[float] The array of thetas, only if requested in the corresponding function parameter """ mol_with_conformers = \ self.dihedral_benchmark.generate_dihedral_conformers( resolution) from openforcefield.topology import Molecule mol = Molecule.from_rdkit(mol_with_conformers) dihedral_energies = list() for i, conformer in enumerate(mol.conformers): energy = self._calc_energy(conformer) dihedral_energies.append(energy) if get_thetas: from rdkit.Chem import rdMolTransforms thetas = list() for conf in mol_with_conformers.GetConformers(): thetas.append( rdMolTransforms.GetDihedralDeg( conf, *self.dihedral_benchmark.atom_indexes)) return dihedral_energies, thetas return dihedral_energies
def get_dihs(f, atid=None): #rdkit mol = Chem.MolFromMolFile(f, removeHs=False, sanitize=False) c = mol.GetConformer() if atid == None: atid = enumerateDihs(f) dih = [] for i in range(len(atid)): bond = mol.GetBondBetweenAtoms(atid[i][1], atid[i][2]) a2 = mol.GetAtomWithIdx(atid[i][1]) a3 = mol.GetAtomWithIdx(atid[i][2]) if a2.GetHybridization != Chem.HybridizationType.SP and a3.GetHybridization != Chem.HybridizationType.SP: dih.append( rdt.GetDihedralDeg(c, atid[i][0], atid[i][1], atid[i][2], atid[i][3])) return np.array(dih), atid
def get_dihedrals_withduplicates(self): raw_rot_bonds = self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[!#1]~[!$(*#*)&!D1]-!@[!$(*#*)&!D1]~[!#1]")) raw_rot_bonds += self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[O,S]-[#1]")) raw_rot_bonds += self.molecule.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[NX3;H2]-[#1]")) conf = self.molecule.GetConformer() angles = [] for k, i, j, l in raw_rot_bonds: theta = rdMolTransforms.GetDihedralDeg(conf, k, i, j, l) angles.append([k, i, j, l, theta]) return angles
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 systematic_conformers(mol, init_rdkit_mol, theta=120., charged_fragments=True, ff_variant='UFF', max_iters=200, threads=1, check_stero=False): """Systematic rotation of dihedral angles theta degrees""" # find dihedrals of parent molecule and create all combinations # where the angles are rotated theta degrees. dihedral_idx = RotatableBonds(mol) conf = mol.GetConformer() dihedrals = list() for k, i, j, l in dihedral_idx: mol_dihedral = rdMolTransforms.GetDihedralDeg(conf, k, i, j, l) new_dihedrals = [ mol_dihedral + x * theta for x in range(int(360. / theta)) ] dihedrals.append(new_dihedrals) dihedralCombs = list(itertools.product(*dihedrals)) # Create the conformations according to angle combinations # in dihedralCombs. for idx, dihedrals in enumerate(dihedralCombs): for (k, i, j, l), angle in zip(dihedral_idx, dihedrals): rdMolTransforms.SetDihedralDeg(conf, k, i, j, l, angle) mol.AddConformer(conf, assignId=True) # Clean conformers. Test if structure is corrupted or the stereo # chemistry changed. ff_clean(mol, init_rdkit_mol, ff_variant, max_iters, threads, charged_fragments, check_stero) return mol
def dihedral_measure(sdf_string, position): """ Measure the dihedral angle. Args: sdf_string (string) position (list): 4 atoms defining the dihedral Returns: float value Raises: ValueError: If the lenght of the list is not equal 4. """ if len(position) != 4: raise ValueError("The position needs to be defined by 4 integers") mol = Chem.MolFromMolBlock(sdf_string, removeHs=False) val = float( rdMolTransforms.GetDihedralDeg(mol.GetConformer(), ig(0)(position), ig(1)(position), ig(2)(position), ig(3)(position))) return float('{0:.2f}'.format(val))
def eval_dihedrals(mol, atom1, atom2): """ for aromatic neighbors, evaluate if the dihedral angle is within tolerance that aromaticity isn't broken this function assumes atom1 and atom2 are in valid aromatic systems; filtering should be applied before function call """ a1_idx = atom1.GetIdx() a2_idx = atom2.GetIdx() n1 = [a for a in atom1.GetNeighbors() if check_aromatic(a) and a.GetIdx() != a2_idx] n2 = [a for a in atom2.GetNeighbors() if check_aromatic(a) and a.GetIdx() != a1_idx] mol_conf = mol.GetConformers()[0] # assume there is only one conformer dihedrals = [] for nd1 in n1: for nd2 in n2: dihedrals.append(rdMolTransforms.GetDihedralDeg(mol_conf, nd1.GetIdx(), a1_idx, a2_idx, nd2.GetIdx())) abs_diff_dihedrals = [np.abs(np.abs(np.abs(d)-90) - 90) for d in dihedrals] # abs(-180) - 90 = 90. abs(0) - 90 = -90 planar_mean = np.mean(abs_diff_dihedrals) if planar_mean > 20: return False else: return True
def get_conformations(mol, max_number_of_conformations): raw_rot_bonds = mol.GetSubstructMatches( Chem.MolFromSmarts("[!#1]~[!$(*#*)&!D1]-!@[!$(*#*)&!D1]~[!#1]")) raw_rot_bonds += mol.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[O,S]-[#1]")) raw_rot_bonds += mol.GetSubstructMatches( Chem.MolFromSmarts("[*]~[*]-[NX3;H2]-[#1]")) bonds = [] rot_bonds = [] for k, i, j, l in raw_rot_bonds: if (i, j) not in bonds: bonds.append((i, j)) rot_bonds.append((k, i, j, l)) conf = mol.GetConformer() angles = [] for k, i, j, l in rot_bonds: theta = rdMolTransforms.GetDihedralDeg(conf, k, i, j, l) angles.append([theta, theta + 120., theta - 120.]) angle_combinations = list(itertools.product(*angles)) number_of_conformations = len(angle_combinations) if number_of_conformations > max_number_of_conformations: angle_combinations = get_subset(number_of_conformations, max_number_of_conformations, angle_combinations) for angle_combination in angle_combinations: for (k, i, j, l), angle in zip(rot_bonds, angle_combination): rdMolTransforms.SetDihedralDeg(conf, k, i, j, l, angle) mol.AddConformer(conf, assignId=True) #print mol.GetNumConformers() return mol
def set_rdkit_dihedrals(conf, rd_mol, index_map, rd_scan, deg_increment=None, deg_abs=None): """ A helper function for setting dihedral angles `conf` is the RDKit conformer with the current xyz information `rd_mol` is the RDKit molecule `indx_map` is an atom index mapping dictionary, keys are xyz_index, values are rd_index `rd_scan` is the torsion scan atom indices corresponding to the RDKit conformer indices Either `deg_increment` or `deg_abs` must be specified for the dihedral increment Returns xyz in an array format ordered according to the map, the elements in the xyz should be identified by the calling function from the context """ if deg_increment is None and deg_abs is None: raise SpeciesError('Cannot set dihedral without either a degree increment or an absolute degree') if deg_increment is not None: deg0 = rdMT.GetDihedralDeg(conf, rd_scan[0], rd_scan[1], rd_scan[2], rd_scan[3]) # get original dihedral deg = deg0 + deg_increment else: deg = deg_abs rdMT.SetDihedralDeg(conf, rd_scan[0], rd_scan[1], rd_scan[2], rd_scan[3], deg) new_xyz = list() for i in range(rd_mol.GetNumAtoms()): new_xyz.append([conf.GetAtomPosition(index_map[i]).x, conf.GetAtomPosition(index_map[i]).y, conf.GetAtomPosition(index_map[i]).z]) return new_xyz
def get_energies(self, resolution=30, get_thetas=False): """ It returns the energies of this energetic profile calculator. Parameters ---------- resolution : float The resolution, in degrees, that is applied when rotating the dihedral rotatable bond. Default is 30 degrees get_thetas : bool Whether to return thetas (dihedral angles) or not. Default is False Returns ------- dihedral_energies : a simtk.unit.Quantity object The array of energies represented with a simtk's Quantity object thetas : list[float] The array of thetas, only if requested in the corresponding function parameter """ import numpy as np from copy import deepcopy from simtk import unit from rdkit.Chem import rdMolTransforms xs = unit.Quantity(np.arange(0, 360, resolution), unit=unit.degrees) ys = unit.Quantity(np.zeros(len(xs)), unit=(unit.kilocalorie / unit.mole)) rdkit_mol = deepcopy(self.dihedral_benchmark.molecule.rdkit_molecule) conformer = rdkit_mol.GetConformer() propers = self.dihedral_benchmark.molecule.propers a1, a2 = self.dihedral_benchmark.rotatable_bond for proper in propers: rot_bond = set((proper.atom2_idx, proper.atom3_idx)) if a1 in rot_bond and a2 in rot_bond: if proper.constant == 0: continue constant = proper.constant prefactor = proper.prefactor periodicity = proper.periodicity phase = proper.phase for j, x in enumerate(xs): rdMolTransforms.SetDihedralDeg( conformer, *self.dihedral_benchmark.atom_indexes, float(x.value_in_unit(unit.degree))) theta = unit.Quantity(value=rdMolTransforms.GetDihedralDeg( conformer, *indexes), unit=unit.degree) ys[j] += constant * ( 1 + prefactor * np.cos(periodicity * theta.value_in_unit(unit.radian) - phase.value_in_unit(unit.radian))) if get_thetas: return ys, xs return ys
def changeAndOpt(rdkit, theta): Chem.SanitizeMol(rdkit) initconf = rdkit.GetConformer() # set outer most dihedral to 180 degrees. smarts_patt = "C-S-C-[C,Si,Ge;H0]" outer_dihedral_idx = find_dihedral_idx(rdkit, smarts_patt) for k, i, j, l in outer_dihedral_idx: rdMolTransforms.SetDihedralDeg(initconf, k, i, j, l, 180.0) # change second outmost dihedral with +-120 degrees. patt = "S-C-[C,Si,Ge;H0]-[C,Si,Ge]" dihedral_idx = find_dihedral_idx(rdkit, patt) new_angles = list() for k, i, j, l in dihedral_idx: init_dihedral_angle = rdMolTransforms.GetDihedralDeg( initconf, k, i, j, l) new_angles.append([ init_dihedral_angle + x * theta for x in range(int(360. / theta)) ]) angle_combinations = list( itertools.product(*new_angles)) # all combinations. for dihedrals in angle_combinations: for (k, i, j, l), angle in zip(dihedral_idx, dihedrals): rdMolTransforms.SetDihedralDeg(initconf, k, i, j, l, angle) rdkit.AddConformer(initconf, assignId=True) rdMolAlign.AlignMolConformers(rdkit) mol_list = list() for idx, conf in enumerate(rdkit.GetConformers()): if idx == 0: continue sdf_txt = Chem.SDWriter.GetText(rdkit, conf.GetId()) m = Chem.MolFromMolBlock(sdf_txt, removeHs=False) conf_name = m.GetProp("_Name") + "-" + str(idx - 1) m.SetProp("_Name", conf_name) mol_list.append(m) # Optimize structures with new dihedrals. confqmmol = QMMol(mol_list, fmt="mol_list", charge=0, multi=1, charged_fragments=True) confqmmol.optimize(program="xtb", method="opt", cpus=24, babelAC=True) # Write xyz files of conformers for newConf in confqmmol.GetConformers(): obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats("sdf", "xyz") newConfm = openbabel.OBMol() obConversion.ReadString(newConfm, Chem.MolToMolBlock(newConf)) new_xyz = obConversion.WriteString(newConfm) with open(newConf.GetProp("_Name") + ".xyz", 'w') as f: f.write(new_xyz)
def set_dehedral_angles(m, theta=120.0, rotate_general=True, rotate_ol=True, rotate_ine=True): """ Systematic rotation of dihedral angles theta degrees Taken from Mads """ rotate_idx_list = list() if rotate_general: smart = "[!#1]~[!$(*#*)&!D1]-!@[!$(*#*)&!D1]~[!#1]" rotate_idx_list += m.GetSubstructMatches(Chem.MolFromSmarts(smart)) if rotate_ol: smart = "[*]~[*]-[O,S]-[#1]" rotate_idx_list += m.GetSubstructMatches(Chem.MolFromSmarts(smart)) if rotate_ine: smart = "[*]~[*]-[NX3;H2]-[#1]" rotate_idx_list += m.GetSubstructMatches(Chem.MolFromSmarts(smart)) # Find unique bonds and dihedral angles indexes idx_bonds = list() idx_dihedral = list() atoms = m.GetAtoms() for k, i, j, l in rotate_idx_list: if (i,j) in idx_bonds: continue idx_bonds.append((i,j)) idx_dihedral.append((k,i,j,l)) print("found", k,i,j,l) print(atoms[k].GetAtomicNum()) print(atoms[i].GetAtomicNum()) print(atoms[j].GetAtomicNum()) print(atoms[l].GetAtomicNum()) # find dihedrals of parent molecule and create all combinations # where the angles are rotated theta degrees. parent = m.GetConformer() # List of alle moveable angles dihedrals = list() for k, i, j, l in idx_dihedral: parent_dihedral = rdMolTransforms.GetDihedralDeg(parent, k, i, j, l) new_dihedrals = [ x*theta for x in range(int(360./theta))] print(new_dihedrals) dihedrals.append(new_dihedrals) # make all possible combinations of dihedral angles dihedral_combinations = list(itertools.product(*dihedrals)) # Create the conformations according to angle combinations for dihedrals in dihedral_combinations: for (k,i,j,l), angle in zip(idx_dihedral, dihedrals): print(k,i,j,l, angle) rdMolTransforms.SetDihedralDeg(parent, k, i, j, l, angle) # translate mol to centroid rdMolTransforms.CanonicalizeConformer(parent) m.AddConformer(parent, assignId=True) return m
def get_energies(self, resolution=30, get_thetas=False): """ It returns the energies of this energetic profile calculator. Parameters ---------- resolution : float The resolution, in degrees, that is applied when rotating the dihedral rotatable bond. Default is 30 degrees get_thetas : bool Whether to return thetas (dihedral angles) or not. Default is False Returns ------- dihedral_energies : a simtk.unit.Quantity object The array of energies represented with a simtk's Quantity object thetas : list[float] The array of thetas, only if requested in the corresponding function parameter """ mol_with_conformers = \ self.dihedral_benchmark.generate_dihedral_conformers( resolution) import tempfile from peleffybenchmarktools.utils import temporary_cd from peleffybenchmarktools.utils.pele import (PELESinglePoint, PELEOutputParser) mol = self.dihedral_benchmark.molecule dihedral_energies = list() with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): for conf in mol_with_conformers.GetConformers(): # Write conformation to PDB file mol.set_conformer(conf) mol.to_pdb_file('ligand.pdb') pele_job = PELESinglePoint(PELE_exec=self.PELE_exec, PELE_src=self.PELE_src, PELE_license=self.PELE_license) output_file = pele_job.run( self.dihedral_benchmark.molecule, pdb_path='ligand.pdb', charges_method='gasteiger') parsed_output = PELEOutputParser(output_file) dihedral_energies.append(parsed_output['torsion energy']) if get_thetas: from rdkit.Chem import rdMolTransforms thetas = list() for conf in mol_with_conformers.GetConformers(): thetas.append( rdMolTransforms.GetDihedralDeg( conf, *self.dihedral_benchmark.atom_indexes)) return dihedral_energies, thetas return dihedral_energies