def select_dummy_atoms(all_dummies, helix_dummies, center, positive_pose=True): select = openbabel.OBMol() search_for = "" ## 1.1 start the search for the correct atoms log.info('Searching for dummies with center position ' + str(center) + "...") ## 1.2 find corresponding helix dummy search_for = str(float(center)-1) log.debug("Starting search for: "+search_for) for res in openbabel.OBResidueIter(helix_dummies): log.debug(res.GetNumString()) if float(res.GetNumString()) == float(search_for): log.info('... found dummy number 1 at helix.') select.AddResidue(res) for atom in openbabel.OBResidueAtomIter(res): select.AddAtom(atom) break ## 1.2.1. find next helix dummy search_for = str(float(center)) for res in openbabel.OBResidueIter(helix_dummies): log.debug(res.GetNumString()) if float(res.GetNumString()) == float(search_for): log.info('... found dummy number 2 at helix.') select.AddResidue(res) for atom in openbabel.OBResidueAtomIter(res): select.AddAtom(atom) break ## 1.3 find next-to-center dna dummy search_for = str(float(center)-1) for res in openbabel.OBResidueIter(all_dummies): log.debug(res.GetNumString()) if float(res.GetNumString()) == float(search_for): log.info('... found dummy before center.') select.AddResidue(res) for atom in openbabel.OBResidueAtomIter(res): select.AddAtom(atom) break ## 1.4 find center dna atom search_for = str(float(center)+2) for res in openbabel.OBResidueIter(all_dummies): log.debug(res.GetNumString()) if float(res.GetNumString()) == float(search_for): log.info('... found dummy after center.') select.AddResidue(res) for atom in openbabel.OBResidueAtomIter(res): select.AddAtom(atom) break ## 1.3 check for success if select.NumAtoms() != 4: log.critical("Could not select DNA dummy atoms to align the ligand to. I have selected "+str(select.NumAtoms())+" atoms. Alignment will fail!") return select
def saveMol(prot, outPref, outFmt): # apply eventual patches due to amber top to openbabel format differences and output docking format file currDir = os.getcwd() # adjust H for atom in prot: if atom.atomicnum == 1: atom.OBAtom.SetType('H') for res in ob.OBResidueIter(prot.OBMol): resname = res.GetName() if resname == 'HEM': #nhem=res.GetNum() for atm in ob.OBResidueAtomIter(res): if atm.GetType() == 'FE': atm.SetType('Fe') if atm.GetType() == 'Du': atName = res.GetAtomID(atm).lstrip() atm.SetType(atName[0]) print "save mol2 for docking" templfn = os.path.join(currDir, "%s.%s" % (outPref, outFmt)) out = pb.Outputfile(outFmt, templfn, overwrite=True) out.write(prot) out.close() return templfn
def nameAtoms(self): """Attempts to name atoms """ has_residues = False residue_has_atoms = False atoms_no_name = list(range(0, self.mol.NumAtoms())) # first try to name atoms according to biological # function, i.e. from a PDB file. # OpenBabel has problems with some elements so we need to work around # those here. for residue in openbabel.OBResidueIter(self.mol): has_residues = True if residue.GetNumAtoms() > 0: residue_has_atoms = True for atom in openbabel.OBResidueAtomIter( residue ): atoms_no_name.remove(atom.GetId()) self._atom_names.append( residue.GetAtomID( atom ) ) else: pass # if there are items left in "atoms_no_name" try to name them #print atoms_no_name if len(atoms_no_name) > 0: if self.getVerbose(): print("Info: FragIt [FRAGMENTATION] will now try to name remaining {0:3d} atoms".format(len(atoms_no_name))) for i, id in enumerate(atoms_no_name): atom = self.mol.GetAtom(id+1) self._atom_names.append(atom.GetType()) if self.getVerbose(): print(" atom {0:4d} is forced to have name '{1:s}'".format(id, atom.GetType()))
def CypCenter(protMol): # Find Fe coordinates # Find Virtual O (cpdI) coordinates # Find equations of the hem plane listheme = [ 'C2B', 'CHB', 'C3A', 'C2A', 'CHA', 'C3D', 'C2D', 'CHD', 'C3C', 'C2C', 'CHC', 'C3B' ] Fe_coord = None S_coord = None hemeplane_coor = dict() for res in ob.OBResidueIter(protMol.OBMol): resname = res.GetName() if resname == 'HEM': for atm in ob.OBResidueAtomIter(res): atmname = res.GetAtomID(atm).strip() if atmname in listheme: hemeplane_coor[atmname] = [ atm.GetX(), atm.GetY(), atm.GetZ() ] elif atm.GetType() == 'FE' or atm.GetType( ) == 'Fe' or atmname == 'FE' or atmname == 'FE': Fe_coord = [atm.GetX(), atm.GetY(), atm.GetZ()] #get normal of the plane of the heme ring hemnorm = normhem(hemeplane_coor) catcenter = findOcpd1(hemnorm, Fe_coord, dist=6.0) return catcenter
def MassCenter(residue): wsum = 0 v = [0, 0, 0] for atom in ob.OBResidueAtomIter(residue): w = atom.GetAtomicMass() wsum += w v[0] += w * atom.x() v[1] += w * atom.y() v[2] += w * atom.z() v[0] /= wsum v[1] /= wsum v[2] /= wsum return v
def extract_ligand(obmol, res_name='INH'): """ This function is used to extract the ligands which are always named 'INH' from CSAR structures. """ ligand = ob.OBMol() for residue in ob.OBResidueIter(obmol): if residue.GetName() == res_name: mapping = {} # insert the ligand atoms into the new molecule for i, atom in enumerate(ob.OBResidueAtomIter(residue), 1): ligand.InsertAtom(atom) mapping[atom.GetIdx()] = i # re-create the bonds for atom in ob.OBResidueAtomIter(residue): for bond in ob.OBAtomBondIter(atom): bgn_idx = mapping[bond.GetBeginAtomIdx()] end_idx = mapping[bond.GetEndAtomIdx()] ligand.AddBond(bgn_idx, end_idx, bond.GetBondOrder(), bond.GetFlags()) # remove the ligand from the original structure for atom_idx in sorted(mapping.keys(), reverse=True): atom = obmol.GetAtom(atom_idx) obmol.DeleteAtom(atom) obmol.DeleteResidue(residue) break return pybel.Molecule(ligand)
def getSurrResids(pybelMol, centerDock, radiusRes, listExclude=[]): listRes = [] print 'GETSURRRESIDUE' print centerDock, radiusRes for res in ob.OBResidueIter(pybelMol.OBMol): if not res.GetName() in listExclude: inner = False for atm in ob.OBResidueAtomIter(res): coords = [atm.GetX(), atm.GetY(), atm.GetZ()] if dist(coords, centerDock) < radiusRes: inner = True break if inner: listRes.append(res.GetNum()) return listRes
def get_fingerprint(file_type,file_path): '''file type: file format that is accepted by Openbabel file_path: path to file returns fingerprint based on MACCS''' mol=next(pybel.readfile(file_type,file_path)) fingerprint=[] residues=[x for x in openbabel.OBResidueIter(mol.OBMol)] for i in range(len(residues)-3): mers=residues[i:i+3] mol1=openbabel.OBMol() for r in mers: for atoms in openbabel.OBResidueAtomIter(r): mol1.AddAtom(atoms) mol1.ConnectTheDots() mol2=pybel.Molecule(mol1) fp=[1 if i in list(mol2.calcfp('MACCS').bits) else 0 for i in range(167)] fingerprint.append(fp) return np.asarray(fingerprint)
def residue_groups(self): groupnames = [] groups = [] # force residue perception self.obmol.GetAtom(1).GetResidue() for r in openbabel.OBResidueIter(self.obmol): resgroup = [] for at in openbabel.OBResidueAtomIter(r): resgroup.append(at.GetIdx() - 1) groupnames.append(str(r.GetNum())) groups.append(resgroup) z = zip(groupnames, groups) z.sort(lambda x, y: cmp(int(x[0]), int(y[0]))) groupnames = [x[0] for x in z] groups = [x[1] for x in z] return groups, groupnames
def tryNameFragment(self, atoms): matched_atoms = 0 frag_name = False residues = self.identifyResidues() charge_lbls = ["", "+", "-"] if len(atoms) == 0: raise ValueError("Error: FragIt [FRAGMENTATION] Cannot name empty fragments. Aborting.") if len(atoms) == 1: atom = self.mol.GetAtom(atoms[0]) charge_lbl = charge_lbls[atom.GetFormalCharge()] element = Z2LABEL[atom.GetAtomicNum()] return "{0:s}{1:s}".format(element, charge_lbl) else: for residue in openbabel.OBResidueIter( self.mol ): for atom in openbabel.OBResidueAtomIter( residue ): if atom.GetIdx() in atoms: return residue.GetName() return "None"
def atoms(self): """List of Atoms in the Residue""" return [Atom(atom) for atom in ob.OBResidueAtomIter(self.OBResidue)]
def MolecularWeight(residue): Mw = 0 for atom in ob.OBResidueAtomIter(residue): Mw += atom.GetAtomicMass() return Mw
def PiPi(pdb_file, lig_name, centroid_distance, dih_parallel, dih_tshape): # Get ligand residue and print its name. ligAtomList = [] ligAtomIdList = [] mol = pybel.readfile('pdb', pdb_file).next() print "A total of %s residues" % mol.OBMol.NumResidues() lig = None for res in ob.OBResidueIter(mol.OBMol): # print res.GetName() if res.GetName() == lig_name: lig = res print "Ligand residue name is: ", lig.GetName() break if not lig: print "No ligand residue %s found, please confirm." % lig_name return 0 else: for atom in ob.OBResidueAtomIter(lig): # print atom.GetIdx() ligAtomList.append(atom) ligAtomIdList.append(atom.GetIdx()) # Set ring_id i = 0 for ring in mol.sssr: ring.ring_id = i i += 1 # print ring.ring_id # Determine which rings are from ligand. ligRingList = [] ligAroRingList = [] ligRingIdList = [] recRingList = [] recAroRingList = [] for ring in mol.sssr: for atom in ligAtomList: if ring.IsMember(atom): if ring not in ligRingList: ligRingList.append(ring) ligRingIdList.append(ring.ring_id) print "ligand ring_ID: ", ring.ring_id, if ring.IsAromatic(): print "Aromatic" ligAroRingList.append(ring) else: print "Saturated" for ring in mol.sssr: if ring.ring_id not in ligRingIdList: recRingList.append(ring) if ring.IsAromatic(): recAroRingList.append(ring) print "\nReceptor has ", len(recRingList), " rings,", print " has ", len(recAroRingList), " aromatic rings." # Find and show the rings ligRingCenter = ob.vector3() recRingCenter = ob.vector3() ligNorm1 = ob.vector3() ligNorm2 = ob.vector3() recNorm1 = ob.vector3() recNorm2 = ob.vector3() coord1 = [] coord2 = [] pair = [] # Store the names of the objects pairList = [] psObjectList = [] i = 0 for ligRing in ligAroRingList: ligRing.findCenterAndNormal(ligRingCenter, ligNorm1, ligNorm2) coord1 = [ ligRingCenter.GetX(), ligRingCenter.GetY(), ligRingCenter.GetZ() ] # Create a pseudoatom for the centroid of each ring in the ligand objectName1 = 'psCenter%.2d' % i i += 1 cmd.pseudoatom(object=objectName1, pos=coord1) psObjectList.append(objectName1) for recRing in recAroRingList: recRing.findCenterAndNormal(recRingCenter, recNorm1, recNorm2) dist = ligRingCenter.distSq(recRingCenter) angle = vecAngle(ligNorm1, recNorm1) if (dist**0.5 < centroid_distance and (angle < dih_parallel or angle > dih_tshape)): # the criteria coord2 = [ recRingCenter.GetX(), recRingCenter.GetY(), recRingCenter.GetZ() ] # Create pseudoatom for each lig ring center objectName2 = 'psCenter%.2d' % i i += 1 cmd.pseudoatom(object=objectName2, pos=coord2) psObjectList.append(objectName2) # pair=[coord1,coord2] pair = [objectName1, objectName2] # print "%.4f,%.4f,%.4f" % (pair[1][0],pair[1][1],pair[1][2]) pairList.append(pair) cmd.distance('dist-' + objectName1 + '-' + objectName2, pair[0], pair[1]) print objectName1, objectName2, " angle is : %.2f" % angle
def make_structure(request): def makeResidue(mol, idx, aaatoms): res = mol.NewResidue() res.SetNum(idx) for atom in ob.OBMolAtomIter(mol): if atom.GetIdx() not in aaatoms: res.AddAtom(atom) aminoacids = request.GET.getlist("as") color = request.GET.get("rescol", "#3EC1CD") mol = ob.OBMol() conv = ob.OBConversion() pattern = ob.OBSmartsPattern() pattern.Init("[NX3][$([CX4H1]([*])),$([CX4H2])][CX3](=[OX1])[OX2]") builder = ob.OBBuilder() conv.SetInAndOutFormats("sdf", "svg") conv.AddOption("d", ob.OBConversion.OUTOPTIONS) conv.AddOption("b", ob.OBConversion.OUTOPTIONS, "none") conv.ReadString(mol, str(Substrate.objects.get(pk=int(aminoacids[0])).structure)) pattern.Match(mol) mollist = pattern.GetUMapList()[0] oatom = mol.GetAtom(mollist[4]) catom = mol.GetAtom(mollist[2]) firstnatom = mol.GetAtom(mollist[0]) makeResidue(mol, 0, mollist) i = 1 for aa in aminoacids[1:]: mol2 = ob.OBMol() conv.ReadString(mol2, str(Substrate.objects.get(pk=int(aa)).structure)) pattern.Match(mol2) mollist = pattern.GetUMapList()[0] makeResidue(mol2, i, mollist) molnatoms = mol.NumAtoms() mol += mol2 natom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[0]).GetIdx()) builder.Connect(mol, catom.GetIdx(), natom.GetIdx()) foatom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[4]).GetIdx()) catom = mol.GetAtom(molnatoms + mol2.GetAtom(mollist[2]).GetIdx()) mol.DeleteHydrogens(oatom) mol.DeleteAtom(oatom) natom.SetImplicitValence(3) mol.DeleteHydrogens(natom) mol.AddHydrogens(natom) oatom = foatom i += 1 nidx = firstnatom.GetIdx() oidx = oatom.GetIdx() builder.Build(mol) natom = mol.GetAtom(nidx) oatom = mol.GetAtom(oidx) for res in ob.OBResidueIter(mol): for atom in ob.OBResidueAtomIter(res): for bond in ob.OBAtomBondIter(atom): data = ob.OBPairData() data.SetAttribute("color") data.SetValue(color) bond.CloneData(data) mol.DeleteHydrogens() gen2d = ob.OBOp.FindType("gen2d") gen2d.Do(mol) opp = oatom.GetY() - natom.GetY() adj = oatom.GetX() - natom.GetX() angle = abs(math.atan(opp / adj)) if opp > 0 and adj > 0: pass elif opp > 0 and adj < 0: angle = math.pi - angle elif opp < 0 and adj < 0: angle = math.pi + angle elif opp < 0 and adj > 0: angle = 2 * math.pi - angle angle = -angle mol.Rotate(ob.double_array([math.cos(angle), -math.sin(angle), 0, math.sin(angle), math.cos(angle), 0, 0, 0, 1])) svg = conv.WriteString(mol) # need to get rid of square aspect ratio delstart = svg.find("width") delend = svg.find("svg", delstart) delend = svg.find("viewBox", delend) svgend = svg.rfind("</g>") svg = svg[0:delstart] + svg[delend:svgend] return HttpResponse(svg, mimetype="image/svg+xml")
def generate_fragfile(filename, outtype, ffparams=None, eqgeom=False): # check outtype if outtype not in ["flex", "header", "min"]: sys.exit( 'Invalid argument indicating verbosity of .dfr (%s). Use "flex", "header" or "min".' % outtype) # get basename and file extension base, ext = os.path.splitext(filename) # set openbabel file format obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats(ext[1:], "xyz") # read molecule to OBMol object mol = openbabel.OBMol() obConversion.ReadFile(mol, filename) if ffparams: # get atomic labels from pdb idToAtomicLabel = {} for res in openbabel.OBResidueIter(mol): for atom in openbabel.OBResidueAtomIter(res): idToAtomicLabel[atom.GetId()] = res.GetAtomID(atom).strip() # read force field parameters and store into dictionaries labelToSLabel = {} charges = {} epsilons = {} sigmas = {} bonds = {} angles = {} dihedrals = {} impropers = {} with open(ffparams, 'r') as f: line = f.readline() # read nb params while "$bond" not in line: if line.strip().startswith("#") or not line.strip(): line = f.readline() continue lbl = line.split()[0] charges[lbl] = line.split()[1] epsilons[lbl] = line.split()[2] sigmas[lbl] = line.split()[3] labelToSLabel[lbl] = line.split()[4] line = f.readline() # read bond params line = f.readline() while "$angle" not in line: if line.strip().startswith( "#") or "$end" in line or not line.strip(): line = f.readline() continue line = line.replace("–", "-") # store the constants for the order of the input and the inverse order consts = "\t".join(line.split()[1:]) bonds[line.split()[0]] = consts bonds["-".join(line.split()[0].split("-")[::-1])] = consts line = f.readline() # read angle params line = f.readline() while "$dihedral" not in line: if line.strip().startswith( "#") or "$end" in line or not line.strip(): line = f.readline() continue line = line.replace("–", "-") # store the constants for the order of the input and the inverse order consts = "\t".join(line.split()[1:]) angles[line.split()[0]] = consts angles["-".join(line.split()[0].split("-")[::-1])] = consts line = f.readline() # read dihedrals line = f.readline() while "$improper" not in line: if line.strip().startswith( "#") or "$end" in line or not line.strip(): line = f.readline() continue line = line.replace("–", "-") # store the constants for the order of the input and the inverse order consts = "\t".join(line.split()[1:]) dihedrals[line.split()[0]] = consts dihedrals["-".join(line.split()[0].split("-")[::-1])] = consts line = f.readline() # read impropers line = f.readline() while line: if line.strip().startswith( "#") or "$end" in line or not line.strip(): line = f.readline() continue line = line.replace("–", "-") # store the constants for the order of the input and the inverse order consts = "\t".join(line.split()[1:]) impropers[line.split()[0]] = consts impropers["-".join(line.split()[0].split("-")[::-1])] = consts line = f.readline() # check if there are unused labels for lbl in charges.keys(): fnd = False for i in idToAtomicLabel: if lbl == idToAtomicLabel[i]: fnd = True break if not fnd: print( "!!! WARNING: There are unused atoms in your parameter file (%s) !!!" % lbl) # split the molecule fragments, fragConnection, dummyToAtom = split_mol_fragments_daylight(mol) # dummy atoms ids dummyAtoms = dummyToAtom.keys() # write molecule to .txt file (passed as ljname to DICE) with open(base + ".txt", "w") as f: f.write("*\n1\n") atomToPrint = [] for frag in fragments: fragAtomIterator = openbabel.OBMolAtomIter(frag) for atom in fragAtomIterator: if atom.GetId() not in dummyAtoms: atomToPrint.append(atom) # print number of atoms f.write( str(len(atomToPrint)) + " \t %s (generated with fragGen)\n" % os.path.basename(base)) # dictionary associating Atomic number with rdf label rdfs = {} rdf_label = 1 if ffparams: # sort atoms by index and print (this prints the atoms, e.g., in the same order of the xyz input) for atom in sorted(atomToPrint, key=lambda atom: atom.GetId()): if atom.GetAtomicNum() not in rdfs.keys(): rdfs[atom.GetAtomicNum()] = str(rdf_label) rdf_label += 1 f.write(rdfs[atom.GetAtomicNum()] + " " + str(atom.GetAtomicNum()) + " \t" + str(atom.GetX()) + " \t" + str(atom.GetY()) + " \t" + str(atom.GetZ()) + " \t" + charges[idToAtomicLabel[atom.GetId()]] + "\t" + epsilons[idToAtomicLabel[atom.GetId()]] + "\t" + sigmas[idToAtomicLabel[atom.GetId()]] + "\n") f.write("$end\n") else: # sort atoms by index and print (this prints the atoms, e.g., in the same order of the xyz input) for atom in sorted(atomToPrint, key=lambda atom: atom.GetId()): if atom.GetAtomicNum() not in rdfs.keys(): rdfs[atom.GetAtomicNum()] = str(rdf_label) rdf_label += 1 f.write(rdfs[atom.GetAtomicNum()] + " " + str(atom.GetAtomicNum()) + " \t" + str(atom.GetX()) + " \t" + str(atom.GetY()) + " \t" + str(atom.GetZ()) + " \t" + "q" + "\t" + "epsilon" + "\t" + "sigma\n") f.write("$end\n") # write info to dfr file with open(base + ".dfr", "w") as f: # fragments and fragments connections are printed to every outtype f.write("$atoms fragments\n") fragslst = [] for frag in fragments: f.write(frag.GetTitle() + "\t[ ") fragAtomIterator = openbabel.OBMolAtomIter(frag) atomlst = [ str(dummyToAtom[x.GetId()] + 1) if x.GetId() in dummyAtoms else str(x.GetId() + 1) for x in fragAtomIterator ] fragslst.append(atomlst) for atom in atomlst: f.write(atom + "\t") if outtype == "min" or outtype == "header": f.write("] R\n") else: f.write("] F\n") f.write("$end atoms fragments\n") f.write("\n$fragment connection\n") for frag1, frag2 in fragConnection: f.write(frag1 + "\t" + frag2 + "\n") f.write("$end fragment connection\n") # bonds are printed to every outtype that is not header, since we need a connection matrix if outtype != "header": f.write("\n$bond\n") bondIterator = openbabel.OBMolBondIter(mol) if ffparams: for bond in bondIterator: try: if eqgeom: f.write( str(bond.GetBeginAtom().GetId() + 1) + " " + str(bond.GetEndAtom().GetId() + 1) + " \t" + bonds[labelToSLabel[idToAtomicLabel[ bond.GetBeginAtom().GetId()]] + "-" + labelToSLabel[idToAtomicLabel[ bond.GetEndAtom().GetId()]]].split() [0] + "\t" + str("%.6f" % bond.GetLength()) + "\n") else: f.write( str(bond.GetBeginAtom().GetId() + 1) + " " + str(bond.GetEndAtom().GetId() + 1) + " \t" + bonds[labelToSLabel[idToAtomicLabel[ bond.GetBeginAtom().GetId()]] + "-" + labelToSLabel[idToAtomicLabel[ bond.GetEndAtom().GetId()]]] + "\n") except KeyError as e: print( "The parameters for atoms %d %d (%s) was not found in the bonds list\n" % (bond.GetBeginAtom().GetId() + 1, bond.GetEndAtom().GetId() + 1, e)) raise else: for bond in bondIterator: f.write( str(bond.GetBeginAtom().GetId() + 1) + " " + str(bond.GetEndAtom().GetId() + 1) + " \t0.0\t" + str("%.6f" % bond.GetLength()) + "\n") f.write("$end bond\n") # angles are only printed for outtype flex if outtype == "flex": f.write("\n$angle\n") angleIterator = openbabel.OBMolAngleIter(mol) if ffparams: for angle in angleIterator: try: if eqgeom: atom2 = mol.GetAtomById(angle[0]) atom1 = mol.GetAtomById(angle[1]) atom3 = mol.GetAtomById(angle[2]) aparams = angles[ labelToSLabel[idToAtomicLabel[angle[1]]] + "-" + labelToSLabel[idToAtomicLabel[angle[0]]] + "-" + labelToSLabel[idToAtomicLabel[ angle[2]]]].split() f.write( str(angle[1] + 1) + " " + str(angle[0] + 1) + " " + str(angle[2] + 1) + " \t" + aparams[0] + "\t" + aparams[1] + "\t" + str("%.6f" % mol.GetAngle(atom1, atom2, atom3)) + "\n") else: f.write( str(angle[1] + 1) + " " + str(angle[0] + 1) + " " + str(angle[2] + 1) + " \t" + angles[ labelToSLabel[idToAtomicLabel[angle[1]]] + "-" + labelToSLabel[idToAtomicLabel[angle[0]]] + "-" + labelToSLabel[idToAtomicLabel[angle[2]]]] + "\n") except KeyError as e: print( "The parameters for atoms %d %d %d (%s) was not found in the angles list\n" % (angle[1] + 1, angle[0] + 1, angle[2] + 1, e)) raise else: for angle in angleIterator: # carefully select the atoms to find the angle atom2 = mol.GetAtomById(angle[0]) atom1 = mol.GetAtomById(angle[1]) atom3 = mol.GetAtomById(angle[2]) f.write( str(angle[1] + 1) + " " + str(angle[0] + 1) + " " + str(angle[2] + 1) + " \tharmonic\tK\t" + str("%.6f" % mol.GetAngle(atom1, atom2, atom3)) + "\n") f.write("$end angle\n") # all the dihedrals are printed to outtype flex, but only connection between fragments are printed if outtype is min if outtype == "flex": f.write("\n$dihedral\n") torsionIterator = openbabel.OBMolTorsionIter(mol) if ffparams: for torsional in torsionIterator: # Need to sum 1: http://forums.openbabel.org/Rotable-bonds-tp957795p957798.html torsidx = [str(x + 1) for x in torsional] try: f.write(torsidx[0] + " " + torsidx[1] + " " + torsidx[2] + " " + torsidx[3] + " \t" + dihedrals["-".join([ labelToSLabel[idToAtomicLabel[x]] for x in torsional ])] + "\n") except KeyError as e: print( "The parameters for atoms %s %s %s %s (%s) was not found in the dihedrals list\n" % (torsidx[0], torsidx[1], torsidx[2], torsidx[3], e)) raise else: for torsional in torsionIterator: # Need to sum 1: http://forums.openbabel.org/Rotable-bonds-tp957795p957798.html torsional = [str(x + 1) for x in torsional] f.write(torsional[0] + " " + torsional[1] + " " + torsional[2] + " " + torsional[3] + " \tTYPE\tV1\tV2\tV3\tf1\tf2\tf3\n") f.write("$end dihedral\n") # improper dihedral = carbon with only 3 atoms connected to it (SP2 hybridization) # angle found following this definition --> http://cbio.bmt.tue.nl/pumma/index.php/Theory/Potentials f.write("\n$improper dihedral\n") atomIterator = openbabel.OBMolAtomIter(mol) for atom in atomIterator: # print(atom.GetHyb(), atom.GetAtomicNum(), atom.GetValence()) # if atom.GetAtomicNum() == 6 and atom.GetValence() == 3: if atom.GetHyb() == 2 and atom.GetValence() == 3: bondIterator = atom.BeginBonds() nbrAtom = atom.BeginNbrAtom(bondIterator) connectedAtoms = [] connectedAtoms.append(nbrAtom) for i in range(2): nbrAtom = atom.NextNbrAtom(bondIterator) connectedAtoms.append(nbrAtom) if ffparams: torsional = [ atom.GetId(), connectedAtoms[0].GetId(), connectedAtoms[1].GetId(), connectedAtoms[2].GetId() ] # create all the permutations to check if one is found perms = list(itertools.permutations(torsional[1:])) nfound = 0 for perm in perms: try: joined = "-".join([ labelToSLabel[idToAtomicLabel[ torsional[0]]] ] + [ labelToSLabel[idToAtomicLabel[x]] for x in perm ]) f.write( str(torsional[0] + 1) + " " + str(torsional[1] + 1) + " " + str(torsional[2] + 1) + " " + str(torsional[3] + 1) + " \t" + impropers[joined] + "\n") except: nfound += 1 if nfound == len(perms): joined = "-".join( [labelToSLabel[idToAtomicLabel[torsional[0]]] ] + [ labelToSLabel[idToAtomicLabel[x]] for x in perms[0] ]) raise KeyError( "The key %s (or its permutations) were not found in the improper dihedrals list\n" % (joined)) else: torsional = [ atom.GetId() + 1, connectedAtoms[0].GetId() + 1, connectedAtoms[1].GetId() + 1, connectedAtoms[2].GetId() + 1 ] torsionAngle = mol.GetTorsion(torsional[0], torsional[1], torsional[2], torsional[3]) f.write( str(torsional[0]) + " " + str(torsional[1]) + " " + str(torsional[2]) + " " + str(torsional[3]) + " \tV2\t" + str("%.6f" % torsionAngle) + "\n") f.write("$end improper dihedral\n") elif outtype == "min": torsionIterator = openbabel.OBMolTorsionIter(mol) # tjf = torsionals that join fragments tjf = [] # find the tjfs by checking if all the atoms of a torsional belong to the same fragment for tors in torsionIterator: tors = [str(x + 1) for x in tors] istjf = True for atomlst in fragslst: if (tors[0] in atomlst) and (tors[1] in atomlst) and ( tors[2] in atomlst) and (tors[3] in atomlst): istjf = False break if istjf: tjf.append(tors) f.write("\n$dihedral\n") if ffparams: for torsidx in tjf: torsional = [int(x) - 1 for x in torsidx] try: f.write(torsidx[0] + " " + torsidx[1] + " " + torsidx[2] + " " + torsidx[3] + " \t" + dihedrals["-".join([ labelToSLabel[idToAtomicLabel[x]] for x in torsional ])] + "\n") except KeyError as e: print( "The parameters for atoms %s %s %s %s (%s) was not found in the dihedrals list\n" % (torsidx[0], torsidx[1], torsidx[2], torsidx[3], e)) raise else: for torsional in tjf: f.write(torsional[0] + " " + torsional[1] + " " + torsional[2] + " " + torsional[3] + " \tTYPE\tV1\tV2\tV3\tf1\tf2\tf3\n") f.write("$end dihedral\n") # create directory to store the fragments if not os.path.exists(base + "_fragments"): os.makedirs(base + "_fragments") # write framents to the cml files for frag in fragments: obConversion.WriteFile( frag, os.path.join( base + "_fragments", os.path.basename(filename).split(".")[0] + "_fragment" + frag.GetTitle() + ".xyz"))
def atoms(self): return [Atom(atom) for atom in ob.OBResidueAtomIter(self.OBResidue)]
def find_PiPi(pdb_file, lig_name, centroid_distance=5.0, dih_parallel=25, dih_tshape=80, verbose=1): """ Find Pi-Pi interactions around the specified ligand residue from the pdb file. :param pdb_file: path of the target file in PDB format. :param lig_name: ligand residue name. :param centroid_distance: Max ring centroid distance :param dih_parallel: Max dihedral (parallel) :param dih_tshape: Min dihedral (T-shaped) :return: number of Pi-Pi interactions found """ # Get ligand residue and print its name. ligAtomList = [] ligAtomIdList = [] mol = next(pybel.readfile('pdb', pdb_file)) if verbose: print("A total of %s residues" % mol.OBMol.NumResidues()) lig = None for res in ob.OBResidueIter(mol.OBMol): # print res.GetName() if res.GetName() == lig_name: lig = res if verbose: print("Ligand residue name is:", lig.GetName()) break if not lig: if verbose: print("No ligand residue %s found, please confirm." % lig_name) return -1 else: for atom in ob.OBResidueAtomIter(lig): # print atom.GetIdx() ligAtomList.append(atom) ligAtomIdList.append(atom.GetIdx()) # Set ring_id i = 0 for ring in mol.sssr: ring.ring_id = i i += 1 # print ring.ring_id # Determine which rings are from ligand. ligRingList = [] ligAroRingList = [] ligRingIdList = [] recRingList = [] recAroRingList = [] for ring in mol.sssr: for atom in ligAtomList: if ring.IsMember(atom): if ring not in ligRingList: ligRingList.append(ring) ligRingIdList.append(ring.ring_id) if verbose: print("ligand ring_ID: ", ring.ring_id, end=' ') if ring.IsAromatic(): if verbose: print("aromatic") ligAroRingList.append(ring) else: if verbose: print("saturated") for ring in mol.sssr: if ring.ring_id not in ligRingIdList: recRingList.append(ring) if ring.IsAromatic(): recAroRingList.append(ring) if verbose: print("\nReceptor has ", len(recRingList), " rings,", end=' ') if verbose: print(" has ", len(recAroRingList), " aromatic rings.") # Find and show the rings ligRingCenter = ob.vector3() recRingCenter = ob.vector3() ligNorm1 = ob.vector3() ligNorm2 = ob.vector3() recNorm1 = ob.vector3() recNorm2 = ob.vector3() count = 0 lig_ring_index = 0 for ligRing in ligAroRingList: lig_ring_index += 1 ligRing.findCenterAndNormal(ligRingCenter, ligNorm1, ligNorm2) rec_ring_index = 0 for recRing in recAroRingList: rec_ring_index += 1 recRing.findCenterAndNormal(recRingCenter, recNorm1, recNorm2) dist = ligRingCenter.distSq(recRingCenter)**0.5 angle = vecAngle(ligNorm1, recNorm1) if (dist < centroid_distance and (angle < dih_parallel or angle > dih_tshape)): # the criteria count += 1 if verbose: print( "Pi-Pi ring pairs: %3s,%3s Angle(deg.): %5.2f Distance(A): %.2f" % (recRing.ring_id, ligRing.ring_id, angle, dist)) if verbose: print("Total Pi-Pi interactions:", count) return count
obmol = mol.OBMol obres = "" numofresidue = 0 for res in ob.OBResidueIter(obmol): if res.GetName() == ligandname: numofresidue += 1 obres = res if numofresidue == 1: npcoords = numpy.array(coords) print "Found ", obres.GetName(), " ", obres.GetIdx(), \ " chain: ", obres.GetChain() near_residues = {} for obatom in ob.OBResidueAtomIter(obres): atomcoord = numpy.array([obatom.x(), obatom.y(), obatom.z()]) dist = numpy.sqrt(numpy.sum((npcoords - atomcoord)**2, axis=1)) print " %10.3f %10.3f %10.3f %s"%(obatom.x(), \ obatom.y(), obatom.z(), obres.GetAtomID(obatom)) for index in numpy.flatnonzero(dist < args.mindist): res = obatoms[index].GetResidue() uniqname = res.GetName()+ "_" + str(res.GetIdx()) + "_" + \ res.GetChain() near_residues[uniqname] = res print "Now copying original molecule and removing atoms" extract_pdb = ob.OBMol(obmol) atomtoremove = [] for res in ob.OBResidueIter(extract_pdb):
def parse_mol_info(fname, fcharges, axis, buffa, buffo, pbcbonds, printdih, ignorebonds, ignoreimproper): iaxis = {"x": 0, "y": 1, "z": 2} if axis in iaxis: repaxis = iaxis[axis] else: print("Error: invalid axis") sys.exit(0) if fcharges: chargesLabel = {} with open(fcharges, "r") as f: for line in f: chargesLabel[line.split()[0]] = float(line.split()[1]) # set openbabel file format base, ext = os.path.splitext(fname) obConversion = openbabel.OBConversion() obConversion.SetInAndOutFormats(ext[1:], "xyz") # trick to disable ring perception and make the ReadFile waaaay faster # Source: https://sourceforge.net/p/openbabel/mailman/openbabel-discuss/thread/56e1812d-396a-db7c-096d-d378a077853f%40ipcms.unistra.fr/#msg36225392 obConversion.AddOption("b", openbabel.OBConversion.INOPTIONS) # read molecule to OBMol object mol = openbabel.OBMol() obConversion.ReadFile(mol, fname) mol.ConnectTheDots() # necessary because of the 'b' INOPTION # split the molecules molecules = mol.Separate() # detect the molecules types mTypes = {} mapmTypes = {} atomIdToMol = {} nty = 0 for i, submol in enumerate(molecules, start=1): atomiter = openbabel.OBMolAtomIter(submol) atlist = [] for at in atomiter: atlist.append(at.GetAtomicNum()) atomIdToMol[at.GetId()] = i foundType = None for ty in mTypes: # check if there's already a molecule of this type if atlist == mTypes[ty]: foundType = ty # if not, create a new type if not foundType: nty += 1 foundType = nty mTypes[nty] = atlist mapmTypes[i] = foundType # get atomic labels from pdb idToAtomicLabel = {} if ext[1:] == "pdb": for res in openbabel.OBResidueIter(mol): for atom in openbabel.OBResidueAtomIter(res): if (atomIdToMol[atom.GetId()] > 1) and (len(mTypes) > 1): idToAtomicLabel[ atom.GetId()] = res.GetAtomID(atom).strip() + str( mapmTypes[atomIdToMol[atom.GetId()]]) else: idToAtomicLabel[atom.GetId()] = res.GetAtomID(atom).strip() else: if not ob3: etab = openbabel.OBElementTable() for atom in openbabel.OBMolAtomIter(mol): if (atomIdToMol[atom.GetId()] > 1) and (len(mTypes) > 1): if ob3: idToAtomicLabel[atom.GetId()] = openbabel.GetSymbol( atom.GetAtomicNum()) + str( mapmTypes[atomIdToMol[atom.GetId()]]) else: idToAtomicLabel[atom.GetId()] = etab.GetSymbol( atom.GetAtomicNum()) + str( mapmTypes[atomIdToMol[atom.GetId()]]) else: if ob3: idToAtomicLabel[atom.GetId()] = openbabel.GetSymbol( atom.GetAtomicNum()) else: idToAtomicLabel[atom.GetId()] = etab.GetSymbol( atom.GetAtomicNum()) # print(idToAtomicLabel) # identify atom types and get masses outMasses = "Masses\n\n" massTypes = {} mapTypes = {} nmassTypes = 0 atomIterator = openbabel.OBMolAtomIter(mol) for atom in atomIterator: i = atom.GetId() if idToAtomicLabel[i] not in massTypes: nmassTypes += 1 mapTypes[nmassTypes] = idToAtomicLabel[i] massTypes[idToAtomicLabel[i]] = nmassTypes outMasses += "\t%d\t%.3f\t# %s\n" % ( nmassTypes, atom.GetAtomicMass(), idToAtomicLabel[i]) # create atoms list outAtoms = "Atoms # full\n\n" xmin = float("inf") xmax = float("-inf") ymin = float("inf") ymax = float("-inf") zmin = float("inf") zmax = float("-inf") natoms = 0 acoords = [] for mnum, imol in enumerate(molecules, start=1): atomIterator = openbabel.OBMolAtomIter(imol) for atom in sorted(atomIterator, key=lambda x: x.GetId()): natoms += 1 i = atom.GetId() apos = (atom.GetX(), atom.GetY(), atom.GetZ()) acoords.append(Atom(atom.GetAtomicNum(), apos)) # look for the maximum and minimum x for the box (improve later with numpy and all coordinates) if apos[0] > xmax: xmax = apos[0] if apos[0] < xmin: xmin = apos[0] if apos[1] > ymax: ymax = apos[1] if apos[1] < ymin: ymin = apos[1] if apos[2] > zmax: zmax = apos[2] if apos[2] < zmin: zmin = apos[2] if fcharges: outAtoms += "\t%d\t%d\t%d\t%.6f\t%.4f\t%.4f\t%.4f\t# %s\n" % ( i + 1, mnum, massTypes[idToAtomicLabel[i]], chargesLabel[idToAtomicLabel[i]], atom.GetX(), atom.GetY(), atom.GetZ(), idToAtomicLabel[i]) else: outAtoms += "\t%d\t%d\t%d\tX.XXXXXX\t%.4f\t%.4f\t%.4f\t# %s\n" % ( i + 1, mnum, massTypes[idToAtomicLabel[i]], atom.GetX(), atom.GetY(), atom.GetZ(), idToAtomicLabel[i]) # define box shape and size try: fromBounds = False rcell = mol.GetData(12) cell = openbabel.toUnitCell(rcell) v1 = [ cell.GetCellVectors()[0].GetX(), cell.GetCellVectors()[0].GetY(), cell.GetCellVectors()[0].GetZ() ] v2 = [ cell.GetCellVectors()[1].GetX(), cell.GetCellVectors()[1].GetY(), cell.GetCellVectors()[1].GetZ() ] v3 = [ cell.GetCellVectors()[2].GetX(), cell.GetCellVectors()[2].GetY(), cell.GetCellVectors()[2].GetZ() ] boxinfo = [v1, v2, v3] orthogonal = True for i, array in enumerate(boxinfo): for j in range(3): if i == j: continue if not math.isclose(0., array[j], abs_tol=1e-6): orthogonal = False except: fromBounds = True v1 = [xmax - xmin, 0., 0.] v2 = [0., ymax - ymin, 0.] v3 = [0., 0., zmax - zmin] orthogonal = True # add buffer if orthogonal: buf = [] boxinfo = [v1, v2, v3] for i, val in enumerate(boxinfo[repaxis]): if i == repaxis: buf.append(val + buffa) else: buf.append(val) boxinfo[repaxis] = buf for i in range(3): if i == repaxis: continue buf = [] for j, val in enumerate(boxinfo[i]): if j == i: buf.append(val + buffo) else: buf.append(val) boxinfo[i] = buf # print(boxinfo) # Duplicate to get the bonds in the PBC. Taken from (method _crd2bond): # https://github.com/tongzhugroup/mddatasetbuilder/blob/66eb0f15e972be0f5534dcda27af253cd8891ff2/mddatasetbuilder/detect.py#L213 if pbcbonds: acoords = Atoms(acoords, cell=boxinfo, pbc=True) repatoms = acoords.repeat( 2 )[natoms:] # repeat the unit cell in each direction (len(repatoms) = 7*natoms) tree = cKDTree(acoords.get_positions()) d = tree.query(repatoms.get_positions(), k=1)[0] nearest = d < 8. ghost_atoms = repatoms[nearest] realnumber = np.where(nearest)[0] % natoms acoords += ghost_atoms write("replicated.xyz", acoords) # write the structure with the replicated atoms # write new mol with new bonds nmol = openbabel.OBMol() nmol.BeginModify() for idx, (num, position) in enumerate( zip(acoords.get_atomic_numbers(), acoords.positions)): a = nmol.NewAtom(idx) a.SetAtomicNum(int(num)) a.SetVector(*position) nmol.ConnectTheDots() # nmol.PerceiveBondOrders() # super slow becauses it looks for rings nmol.EndModify() else: acoords = Atoms(acoords, cell=boxinfo, pbc=False) nmol = openbabel.OBMol() nmol.BeginModify() for idx, (num, position) in enumerate( zip(acoords.get_atomic_numbers(), acoords.positions)): a = nmol.NewAtom(idx) a.SetAtomicNum(int(num)) a.SetVector(*position) nmol.ConnectTheDots() # nmol.PerceiveBondOrders() # super slow becauses it looks for rings nmol.EndModify() # identify bond types and create bond list outBonds = "Bonds # harmonic\n\n" bondTypes = {} mapbTypes = {} nbondTypes = 0 nbonds = 0 bondsToDelete = [] bondIterators = [] if ignorebonds: sepmols = nmol.Separate() for smol in sepmols[1:]: bondIterators.append(openbabel.OBMolBondIter(smol)) else: bondIterators.append(openbabel.OBMolBondIter(nmol)) lastidx = 1 for iterator in bondIterators: for i, bond in enumerate(iterator, lastidx): b1 = bond.GetBeginAtom().GetId() b2 = bond.GetEndAtom().GetId() # check if its a bond of the replica only if (b1 >= natoms) and (b2 >= natoms): bondsToDelete.append(bond) continue # remap to a real atom if needed if b1 >= natoms: b1 = realnumber[b1 - natoms] if b2 >= natoms: b2 = realnumber[b2 - natoms] # identify bond type btype1 = "%s - %s" % (idToAtomicLabel[b1], idToAtomicLabel[b2]) btype2 = "%s - %s" % (idToAtomicLabel[b2], idToAtomicLabel[b1]) if btype1 in bondTypes: bondid = bondTypes[btype1] bstring = btype1 elif btype2 in bondTypes: bondid = bondTypes[btype2] bstring = btype2 else: nbondTypes += 1 mapbTypes[nbondTypes] = btype1 bondid = nbondTypes bondTypes[btype1] = nbondTypes bstring = btype1 nbonds += 1 outBonds += "\t%d\t%d\t%d\t%d\t# %s\n" % (nbonds, bondid, b1 + 1, b2 + 1, bstring) lastidx = i # delete the bonds of atoms from other replicas for bond in bondsToDelete: nmol.DeleteBond(bond) # identify angle types and create angle list angleTypes = {} mapaTypes = {} nangleTypes = 0 nangles = 0 angleIterators = [] if ignorebonds: sepmols = nmol.Separate() for smol in sepmols[1:]: smol.FindAngles() angleIterators.append(openbabel.OBMolAngleIter(smol)) prevnumatoms = sepmols[0].NumAtoms() else: nmol.FindAngles() angleIterators.append(openbabel.OBMolAngleIter(nmol)) outAngles = "Angles # harmonic\n\n" lastidx = 1 for j, iterator in enumerate(angleIterators, 1): for i, angle in enumerate(iterator, lastidx): if ignorebonds: a1 = angle[1] + prevnumatoms a2 = angle[0] + prevnumatoms a3 = angle[2] + prevnumatoms else: a1 = angle[1] a2 = angle[0] a3 = angle[2] # remap to a real atom if needed if a1 >= natoms: a1 = realnumber[a1 - natoms] if a2 >= natoms: a2 = realnumber[a2 - natoms] if a3 >= natoms: a3 = realnumber[a3 - natoms] atype1 = "%s - %s - %s" % ( idToAtomicLabel[a1], idToAtomicLabel[a2], idToAtomicLabel[a3]) atype2 = "%s - %s - %s" % ( idToAtomicLabel[a3], idToAtomicLabel[a2], idToAtomicLabel[a1]) if atype1 in angleTypes: angleid = angleTypes[atype1] astring = atype1 elif atype2 in angleTypes: angleid = angleTypes[atype2] astring = atype2 else: nangleTypes += 1 mapaTypes[nangleTypes] = atype1 angleid = nangleTypes angleTypes[atype1] = nangleTypes astring = atype1 nangles += 1 outAngles += "\t%d\t%d\t%d\t%d\t%d\t# %s\n" % ( nangles, angleid, a1 + 1, a2 + 1, a3 + 1, astring) lastidx = i if ignorebonds: prevnumatoms += sepmols[j].NumAtoms() # identify dihedral types and create dihedral list if printdih: dihedralTypes = {} mapdTypes = {} ndihedralTypes = 0 ndihedrals = 0 dihedralIterators = [] if ignorebonds: sepmols = nmol.Separate() for smol in sepmols[1:]: smol.FindTorsions() dihedralIterators.append(openbabel.OBMolTorsionIter(smol)) else: nmol.FindTorsions() dihedralIterators.append(openbabel.OBMolTorsionIter(nmol)) outDihedrals = "Dihedrals # charmmfsw\n\n" lastidx = 1 for iterator in dihedralIterators: for i, dihedral in enumerate(iterator, lastidx): a1 = dihedral[0] a2 = dihedral[1] a3 = dihedral[2] a4 = dihedral[3] # remap to a real atom if needed if a1 >= natoms: a1 = realnumber[a1 - natoms] if a2 >= natoms: a2 = realnumber[a2 - natoms] if a3 >= natoms: a3 = realnumber[a3 - natoms] if a4 >= natoms: a4 = realnumber[a4 - natoms] dtype1 = "%s - %s - %s - %s" % ( idToAtomicLabel[a1], idToAtomicLabel[a2], idToAtomicLabel[a3], idToAtomicLabel[a4]) dtype2 = "%s - %s - %s - %s" % ( idToAtomicLabel[a4], idToAtomicLabel[a3], idToAtomicLabel[a2], idToAtomicLabel[a1]) if dtype1 in dihedralTypes: dihedralid = dihedralTypes[dtype1] dstring = dtype1 elif dtype2 in dihedralTypes: dihedralid = dihedralTypes[dtype2] dstring = dtype2 else: ndihedralTypes += 1 mapdTypes[ndihedralTypes] = dtype1 dihedralid = ndihedralTypes dihedralTypes[dtype1] = ndihedralTypes dstring = dtype1 ndihedrals += 1 outDihedrals += "\t%d\t%d\t%d\t%d\t%d\t%d\t# %s\n" % ( ndihedrals, dihedralid, a1 + 1, a2 + 1, a3 + 1, a4 + 1, dstring) lastidx = i if not ignoreimproper: # look for the improper dihedrals improperDihedralTypes = {} mapiDTypes = {} niDihedralTypes = 0 niDihedrals = 0 mollist = [] if ignorebonds: sepmols = nmol.Separate() for smol in sepmols[1:]: smol.PerceiveBondOrders() mollist.append(smol) else: nmol.PerceiveBondOrders() mollist.append(nmol) outImpropers = "Impropers # harmonic\n\n" for imol in mollist: atomIterator = openbabel.OBMolAtomIter(imol) for atom in atomIterator: try: # print(atom.GetHyb(), atom.GetAtomicNum(), atom.GetValence()) expDegree = atom.GetValence() except: # print(atom.GetHyb(), atom.GetAtomicNum(), atom.GetExplicitDegree()) expDegree = atom.GetExplicitDegree() # returns impropers for atoms with connected to other 3 atoms and SP2 hybridization if atom.GetHyb() == 2 and expDegree == 3: connectedAtoms = [] for atom2, depth in openbabel.OBMolAtomBFSIter( imol, atom.GetId() + 1): if depth == 2: connectedAtoms.append(atom2) torsional = [ atom.GetId() + 1, connectedAtoms[0].GetId() + 1, connectedAtoms[1].GetId() + 1, connectedAtoms[2].GetId() + 1 ] a1 = torsional[0] - 1 a2 = torsional[1] - 1 a3 = torsional[2] - 1 a4 = torsional[3] - 1 # remap to a real atom if needed if a1 >= natoms: a1 = realnumber[a1 - natoms] if a2 >= natoms: a2 = realnumber[a2 - natoms] if a3 >= natoms: a3 = realnumber[a3 - natoms] if a4 >= natoms: a4 = realnumber[a4 - natoms] dtype1 = "%s - %s - %s - %s" % ( idToAtomicLabel[a1], idToAtomicLabel[a2], idToAtomicLabel[a3], idToAtomicLabel[a4]) dtype2 = "%s - %s - %s - %s" % ( idToAtomicLabel[a4], idToAtomicLabel[a3], idToAtomicLabel[a2], idToAtomicLabel[a1]) if dtype1 in improperDihedralTypes: idihedralid = improperDihedralTypes[dtype1] dstring = dtype1 elif dtype2 in improperDihedralTypes: idihedralid = improperDihedralTypes[dtype2] dstring = dtype2 else: niDihedralTypes += 1 mapiDTypes[niDihedralTypes] = dtype1 idihedralid = niDihedralTypes improperDihedralTypes[dtype1] = niDihedralTypes dstring = dtype1 niDihedrals += 1 outImpropers += "\t%d\t%d\t%d\t%d\t%d\t%d\t# %s\n" % ( niDihedrals, idihedralid, a1 + 1, a2 + 1, a3 + 1, a4 + 1, dstring) # print header if printdih and (ndihedrals > 0): if ignoreimproper or (niDihedrals == 0): header = "LAMMPS topology created from %s using pdb2lmp.py - By Henrique Musseli Cezar, 2020\n\n\t%d atoms\n\t%d bonds\n\t%d angles\n\t%d dihedrals\n\n\t%d atom types\n\t%d bond types\n\t%d angle types\n\t%d dihedral types\n\n" % ( fname, natoms, nbonds, nangles, ndihedrals, nmassTypes, nbondTypes, nangleTypes, ndihedralTypes) else: header = "LAMMPS topology created from %s using pdb2lmp.py - By Henrique Musseli Cezar, 2020\n\n\t%d atoms\n\t%d bonds\n\t%d angles\n\t%d dihedrals\n\t%d impropers\n\n\t%d atom types\n\t%d bond types\n\t%d angle types\n\t%d dihedral types\n\t%d improper types\n\n" % ( fname, natoms, nbonds, nangles, ndihedrals, niDihedrals, nmassTypes, nbondTypes, nangleTypes, ndihedralTypes, niDihedralTypes) else: header = "LAMMPS topology created from %s using pdb2lmp.py - By Henrique Musseli Cezar, 2020\n\n\t%d atoms\n\t%d bonds\n\t%d angles\n\n\t%d atom types\n\t%d bond types\n\t%d angle types\n\n" % ( fname, natoms, nbonds, nangles, nmassTypes, nbondTypes, nangleTypes) # add box info if fromBounds: boxsize = [(xmin, xmax), (ymin, ymax), (zmin, zmax)] boxsize[repaxis] = (boxsize[repaxis][0] - buffa / 2., boxsize[repaxis][1] + buffa / 2.) for i in range(3): if i == repaxis: continue boxsize[i] = (boxsize[i][0] - buffo / 2., boxsize[i][1] + buffo / 2.) header += "\t%.8f\t%.8f\t xlo xhi\n\t%.8f\t%.8f\t ylo yhi\n\t%.8f\t%.8f\t zlo zhi\n" % ( boxsize[0][0], boxsize[0][1], boxsize[1][0], boxsize[1][1], boxsize[2][0], boxsize[2][1]) else: if orthogonal: header += "\t%.8f\t%.8f\t xlo xhi\n\t%.8f\t%.8f\t ylo yhi\n\t%.8f\t%.8f\t zlo zhi\n" % ( 0., boxinfo[0][0], 0., boxinfo[1][1], 0., boxinfo[2][2]) else: header += "\t%.8f\t%.8f\t xlo xhi\n\t%.8f\t%.8f\t ylo yhi\n\t%.8f\t%.8f\t zlo zhi\n\t%.8f\t%.8f\t%.8f\t xy xz yz\n" % ( 0., boxinfo[0][0], 0., boxinfo[1][1], 0., boxinfo[2][2], boxinfo[1][0], boxinfo[2][0], boxinfo[2][1]) # print Coeffs outCoeffs = "Pair Coeffs\n\n" for i in range(1, nmassTypes + 1): outCoeffs += "\t%d\teps\tsig\t# %s\n" % (i, mapTypes[i]) outCoeffs += "\nBond Coeffs\n\n" for i in range(1, nbondTypes + 1): outCoeffs += "\t%d\tK\tr_0\t# %s\n" % (i, mapbTypes[i]) outCoeffs += "\nAngle Coeffs\n\n" for i in range(1, nangleTypes + 1): outCoeffs += "\t%d\tK\ttetha_0 (deg)\t# %s\n" % (i, mapaTypes[i]) if printdih and (ndihedrals > 0): outCoeffs += "\nDihedral Coeffs\n\n" for i in range(1, ndihedralTypes + 1): outCoeffs += "\t%d\tK\tn\tphi_0 (deg)\tw\t# %s\n" % (i, mapdTypes[i]) if not ignoreimproper and (niDihedralTypes > 0): outCoeffs += "\nImproper Coeffs\n\n" for i in range(1, niDihedralTypes + 1): outCoeffs += "\t%d\tK\txi_0 (deg)\t# %s\n" % (i, mapiDTypes[i]) if printdih and (ndihedrals > 0): if ignoreimproper or (niDihedralTypes == 0): return header + "\n" + outMasses + "\n" + outCoeffs + "\n" + outAtoms + "\n" + outBonds + "\n" + outAngles + "\n" + outDihedrals else: return header + "\n" + outMasses + "\n" + outCoeffs + "\n" + outAtoms + "\n" + outBonds + "\n" + outAngles + "\n" + outDihedrals + "\n" + outImpropers else: return header + "\n" + outMasses + "\n" + outCoeffs + "\n" + outAtoms + "\n" + outBonds + "\n" + outAngles
def getListChanges(pdbmodel): # get modification to apply at pdb to apply amber FF and heme parameters from J Comput Chem. 2012 Jan 15;33(2):119-33 prefnm, extnm = os.path.splitext(pdbmodel) if extnm[1:] != 'pdb': mutref = pb.readfile(extnm[1:], pdbmodel).next() pdbmodel = "%s.pdb" % prefnm mutref.write('pdb', pdbmodel, overwrite=True) outpdb = "%s_tau.pdb" % prefnm reduceCmd = os.path.join(AMBERHOME, 'bin', 'reduce') cmd = [reduceCmd, '-HIS', '-FLIPs', '-quiet', pdbmodel] red = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) optimutpdb, err = red.communicate() optimut = pb.readstring('pdb', optimutpdb) listchanges = [] listTer = [] sCoords = {} nhemseq = None checkCyp = True firstRes = True isCyp = False cypCoord = True ncypseq = None for res in ob.OBResidueIter(optimut.OBMol): resname = res.GetName() resNum = res.GetNum() if firstRes: nres = resNum firstRes = False else: nres += 1 #FIX HIS TAUTOMERS if resname == 'HIS': atmname = [] for atm in ob.OBResidueAtomIter(res): atmname.append(res.GetAtomID(atm).strip()) if ('HE2' in atmname) and ('HD1' in atmname): newResName = "HIP" elif 'HE2' in atmname: newResName = "HIE" elif 'HD1' in atmname: newResName = "HID" else: print "Error in determining the protonation state of HIS %d" % resNum listchanges.append((resNum, 'HIS', newResName)) #GET Fe coordinates for coordinating CYS identification elif resname == 'HEM': isCyp = True nhem = resNum nhemseq = nres #nhem=nres atmname = [] for atm in ob.OBResidueAtomIter(res): if atm.GetType( ) == 'FE' or atm.GetType() == 'Fe' or res.GetAtomID(atm).strip( ) == 'FE' or res.GetAtomID(atm).strip() == 'Fe': Fe_coord = [atm.GetX(), atm.GetY(), atm.GetZ()] #Collect every cysteine S coordinates elif resname == 'CYS': atmname = [] for atm in ob.OBResidueAtomIter(res): atmName = res.GetAtomID(atm).strip() if atmName == 'SG': sCoords[resNum] = {} sCoords[resNum]['coor'] = [ atm.GetX(), atm.GetY(), atm.GetZ() ] #resNum sCoords[resNum]['nseq'] = nres if resname == 'CYP': ncyp = resNum ncypseq = nres checkCyp = False if resname == 'HIH': ncypseq = nres checkCyp = False cypCoord = False for atm in ob.OBResidueAtomIter(res): atmName = res.GetAtomID(atm).strip() if atmName == "OXT": listTer.append(resNum) if isCyp: #Find the coordinating CYS and add to listchanges if cypCoord: if checkCyp: CYP = {'nres': 0, 'dist': 100} for res in sCoords: distS = dist(sCoords[res]['coor'], Fe_coord) print res, distS if distS < CYP['dist']: CYP['dist'] = distS CYP['nres'] = res CYP['nseq'] = sCoords[res]['nseq'] ncypseq = CYP['nseq'] listchanges.append((CYP['nres'], 'CYS', 'CYP')) optimut.removeh() optimut.write('pdb', outpdb, overwrite=True) return (os.path.join(os.getcwd(), outpdb), listchanges, nhemseq, ncypseq, cypCoord)