def calcOmega(piAcidCentroid, piResCentroid): cent1cent2Vec = np.array(piResCentroid["coords"]) - np.array( piAcidCentroid["coords"]) cent1cent2Vec = normalize(cent1cent2Vec) planeNormVec = np.cross(cent1cent2Vec, piAcidCentroid["normVec"]) planeNormVec = normalize(planeNormVec) return degrees(acos(np.inner(planeNormVec, piResCentroid["normVec"])))
def isFlat(allAtomsList, atomsIndList, substituents): """ Sprawdz czy wybrane atomy leza w jednej plaszczyznie. Procedura: na podstawie polozen trzech pierwszych atomow wyznacza sie wektor normalnych do wyznaczonej przez nich plaszczyzny. Nastepnie sprawdzane jest czy kolejne wiazania tworza wektory prostopadle do wektora normalnego. Dopuszczalne jest odchylenie 5 stopni. TODO: Nie lepiej byloby obliczyc tensor momentu bezwladnosci, zdiagonalizowac go i rozstrzygnac na podstawie jego wartosci wlasnych? Wejscie: allAtomsList - lista obiektow Atom (cala czasteczka) atomsIndList - lista indeksow atomow, ktore maja byc zweryfikowane pod wzgledem lezenia w jednej plaszczyznie Wyjscie: verdict - slownik, posiada klucze: isFlat (zmienna logiczna, True jesli struktura jest plaska), normVec (3-elementowa lista float, wspolrzedne wektora normalnego plaszczyzny, jesli struktura nie jest plaska wszystkie jego wspolrzedne sa rowne 0) """ verdict = {'isFlat': False, 'normVec': [0, 0, 0]} if len(atomsIndList) < 3: print("Znaleziono 2-wu elementowy cykl!!!") return verdict norm_vec = getNormVec(allAtomsList, atomsIndList) if len(atomsIndList) <= 3: verdict['normVec'] = norm_vec return verdict centroid = getAverageCoords(allAtomsList, atomsIndList) for i in range(1, len(atomsIndList)): atomInd = atomsIndList[i] D = np.array(allAtomsList[atomInd].get_coord()) new_vec = normalize(centroid - D) if abs(np.inner(new_vec, norm_vec)) > 0.09: return verdict for substituentKey in substituents: D = np.array(allAtomsList[substituentKey].get_coord()) E = np.array(allAtomsList[substituents[substituentKey]].get_coord()) new_vec = normalize(E - D) if abs(np.inner(new_vec, norm_vec)) > 0.20: return verdict verdict['isFlat'] = True verdict['normVec'] = norm_vec verdict['coords'] = centroid return verdict
def getNormVec(allAtomsList, atomsIndList): norm_vec = np.array([0., 0., 0.]) expanded_list = atomsIndList + atomsIndList[:2] for i in range(len(expanded_list) - 2): A = np.array(allAtomsList[expanded_list[i]].get_coord()) B = np.array(allAtomsList[expanded_list[i + 1]].get_coord()) C = np.array(allAtomsList[expanded_list[i + 2]].get_coord()) vec1 = A - B vec2 = B - C norm_vec += normalize(np.cross(vec1, vec2)) return normalize(norm_vec)
def writeAnionPiLinearResults(self, ligand, centroid, lineData, modelIndex, anionGroupId, symmetrizeAlpha=False): resultsFileName = self.linearAnionPiLog ligandCode = ligand.get_resname() ligandId = str(ligand.get_id()[1]) ligandChain = ligand.get_parent().get_id() resultsFile = open(resultsFileName, "a+") vector = lineData.atomsInvolved[1].get_coord( ) - lineData.atomsInvolved[0].get_coord() vector = normalize(vector) inner_prod = np.inner(vector, centroid["normVec"]) if abs(inner_prod) > 1.0: if abs(inner_prod) < 1.1: angle = 0 else: angle = 666 else: angle = degrees(acos(inner_prod)) if symmetrizeAlpha and angle > 90.0: angle = 180 - angle atom = lineData.atomsInvolved[0] anion = atom.get_parent() residueName = anion.get_resname() anionChain = anion.get_parent().get_id() anionId = str(anion.get_id()[1]) centroidCoords = centroid["coords"] anionGroupCoords = getAverageCoords( lineData.atomsInvolved, list(range(len(lineData.atomsInvolved)))) resultsFile.write(self.pdbCode + "\t") resultsFile.write(ligandCode + "\t") resultsFile.write(ligandChain + "\t") resultsFile.write(ligandId + "\t") resultsFile.write(str(centroid["cycleId"]) + "\t") resultsFile.write(residueName + "\t") resultsFile.write(anionChain + "\t") resultsFile.write(anionId + "\t") resultsFile.write(str(anionGroupId) + "\t") resultsFile.write(str(angle) + "\t") resultsFile.write(str(centroidCoords[0]) + "\t") resultsFile.write(str(centroidCoords[1]) + "\t") resultsFile.write(str(centroidCoords[2]) + "\t") resultsFile.write(str(anionGroupCoords[0]) + "\t") resultsFile.write(str(anionGroupCoords[1]) + "\t") resultsFile.write(str(anionGroupCoords[2]) + "\t") resultsFile.write(str(modelIndex) + "\n") resultsFile.close()
def angleNormVecPoint(centroid, point): coords = np.array(point) centroidCoords = np.array(centroid["coords"]) normVec = centroid["normVec"] centrAtomVec = normalize(coords - centroidCoords) inner_prod = np.inner(normVec, centrAtomVec) return degrees(acos(inner_prod))
def calcDirectionalVector(planeData, centroid): vecCoords = [] for pointData in planeData.directionalVector: kind = list(pointData.keys())[0] if kind == "atom": vecCoords.append(pointData[kind].get_coord()) elif kind == "center": atomsList = pointData[kind] vecCoords.append( getAverageCoords(atomsList, list(range(len(atomsList))))) elif kind == "closest": atomsList = pointData[kind] minDist = 1000 closestAtom = None for atom in atomsList: dist = atomDistanceFromCentroid(atom, centroid) if dist < minDist: minDist = dist closestAtom = atom vecCoords.append(closestAtom.get_coord()) vec = normalize(vecCoords[1] - vecCoords[0]) vec2 = normalize(np.array(centroid["coords"]) - vecCoords[1]) inner_prod = np.inner(vec, vec2) if abs(inner_prod) > 1.0: if abs(inner_prod) < 1.1: return 0.0 else: return 666.0 return degrees(acos(inner_prod))
def trigonal(self, atom): number_of_protons_to_add = self.moleculeGraph.nodes[atom]["number_of_protons_to_add"] if number_of_protons_to_add == 0: return rot_angle = math.radians(120.0) bonded_atoms_ids = list(self.moleculeGraph.neighbors(atom)) if len(bonded_atoms_ids) == 0: return if len(bonded_atoms_ids) == 1: A = self.atomList[atom].get_coord() B = self.atomList[ bonded_atoms_ids[0] ].get_coord() Bneighbors = list(self.moleculeGraph.neighbors(bonded_atoms_ids[0])) for cCandidate in Bneighbors: if cCandidate != atom and self.atomList[cCandidate].element in [ "N" , "C" ]: C = self.atomList[cCandidate].get_coord() norm_vec = -normalize(np.cross(A-B, B-C)) break else: norm_vec = normalize( np.cross( B-A, self.anionCoords - A ) ) # norm_vec = get_ortonormal(B-A) bondDirection = B-A for i in range(number_of_protons_to_add): bondDirection = rotateVector(bondDirection, norm_vec, rot_angle) bondDirection = normalize(bondDirection)* self.bond_lengths[ self.atomList[atom].element ] newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) elif len(bonded_atoms_ids) == 2: A = self.atomList[atom].get_coord() B = self.atomList[ bonded_atoms_ids[0] ].get_coord() C = self.atomList[ bonded_atoms_ids[1] ].get_coord() AB = normalize(B-A) AC = normalize(C-A) bondDirection = -(AB+AC) bondDirection = normalize(bondDirection)* self.bond_lengths[ self.atomList[atom].element ] newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) return
def atomAngleNomVecCentroid(atom, centroid): """ Funkcja pomocnicza, oblicza kat pomiedzy kierunkiem od srodka pierscienia do atomu a wektorem normalnym plaszczyzny pierscienia Wejscie: atom - obiekt Atom (Biopython) centroid - slownik, klucze: coords, normVec Wyjscie: kat w stopniach """ atomCoords = np.array(atom.get_coord()) centroidCoords = np.array(centroid["coords"]) normVec = centroid["normVec"] centrAtomVec = normalize(atomCoords - centroidCoords) inner_prod = np.inner(normVec, centrAtomVec) return degrees(acos(inner_prod))
def get_ortonormal(vec): closest2zeroIndex = -1 dist = 100 for i, el in enumerate(vec): if abs(el) < dist: closest2zeroIndex = i dist = abs(el) vecOut = np.array([0.0, 0.0, 0.0]) aInd = (closest2zeroIndex+1)%3 bInd = (closest2zeroIndex+2)%3 if abs(vec[bInd]) < 0.001: vecOut[bInd]=1 return vecOut vecOut[aInd] =1 vecOut[bInd] = -vec[aInd]/vec[bInd] return normalize(vecOut)
def tetrahedral(self, atom): number_of_protons_to_add = self.moleculeGraph.nodes[atom]["number_of_protons_to_add"] rot_angle = math.radians(109.5) if number_of_protons_to_add == 0: return bonded_atoms_ids = list(self.moleculeGraph.neighbors(atom)) if len(bonded_atoms_ids) == 0: return if len(bonded_atoms_ids) == 1: A = self.atomList[atom].get_coord() B = self.atomList[ bonded_atoms_ids[0] ].get_coord() # norm_vec = get_ortonormal(B-A) norm_vec = normalize( np.cross( B-A, self.anionCoords - A ) ) dih_rot = math.radians(120) bondDirection = rotateVector(B-A, norm_vec, rot_angle) bondDirection = normalize(bondDirection)* self.bond_lengths[ self.atomList[atom].element ] for i in range(number_of_protons_to_add): newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) bondDirection = rotateVector(bondDirection, B-A, dih_rot) # 1 bond elif len(bonded_atoms_ids) == 2: A = self.atomList[atom].get_coord() B = self.atomList[ bonded_atoms_ids[0] ].get_coord() C = self.atomList[ bonded_atoms_ids[1] ].get_coord() AB = normalize(B-A) AC = normalize(C-A) axis = AB+AC bondDirection = rotateVector(-AB, axis, math.radians(90)) bondDirection = normalize(bondDirection)*self.bond_lengths[ self.atomList[atom].element ] newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) if number_of_protons_to_add > 1: bondDirection = rotateVector(bondDirection, axis, math.radians(180)) newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) elif len(bonded_atoms_ids) == 3: A = self.atomList[atom].get_coord() B = self.atomList[ bonded_atoms_ids[0] ].get_coord() C = self.atomList[ bonded_atoms_ids[1] ].get_coord() D = self.atomList[ bonded_atoms_ids[2] ].get_coord() AB = normalize(B-A) AC = normalize(C-A) AD = normalize(D-A) bondDirection = -(AB+AC+AD) bondDirection = bondDirection*self.bond_lengths[ self.atomList[atom].element ] newAtomCoords = A + bondDirection self.hydrogenAtomsList.append(HydrogenAtom(newAtomCoords)) self.connected2H.append(atom) return
def writeHbondsResults(self, hDonors, atom, modelIndex): resultsFileName = self.hBondsLog anionAtom = atom["Atom"] anion = anionAtom.get_parent() anionCode = anion.get_resname() anionId = str(anion.get_id()[1]) anionChain = anion.get_parent().get_id() anionCoord = anionAtom.get_coord() resultsFile = open(resultsFileName, "a+") for hDonData in hDonors: hDon = hDonData["donor"] distance = anionAtom - hDon hDonCoords = hDon.get_coord() hDonRes = hDon.get_parent() residueName = hDonRes.get_resname() resChain = hDonRes.get_parent().get_id() resId = str(hDonRes.get_id()[1]) resultsFile.write(self.pdbCode + "\t") resultsFile.write(anionCode + "\t") resultsFile.write(anionChain + "\t") resultsFile.write(anionId + "\t") resultsFile.write(residueName + "\t") resultsFile.write(resChain + "\t") resultsFile.write(resId + "\t") resultsFile.write(atom["AnionType"] + "\t") resultsFile.write(anionAtom.element + "\t") resultsFile.write(str(anionAtom.anionData.anionId) + "\t") resultsFile.write(str(anionCoord[0]) + "\t") resultsFile.write(str(anionCoord[1]) + "\t") resultsFile.write(str(anionCoord[2]) + "\t") resultsFile.write(hDon.element + "\t" + hDon.element + "\t") resultsFile.write(str(hDonCoords[0]) + "\t") resultsFile.write(str(hDonCoords[1]) + "\t") resultsFile.write(str(hDonCoords[2]) + "\t") hydrogenAtom = hDonData["hydrogen"] hydrogenCoords = hydrogenAtom.get_coord() resultsFile.write(str(hydrogenCoords[0]) + "\t") resultsFile.write(str(hydrogenCoords[1]) + "\t") resultsFile.write(str(hydrogenCoords[2]) + "\t") resultsFile.write(str(hDonData["HFromExp"]) + "\t") vec1 = normalize(anionCoord - hydrogenCoords) vec2 = normalize(hDonCoords - hydrogenCoords) angle = degrees(acos(np.inner(vec1, vec2))) hDistance = anionAtom - hydrogenAtom resultsFile.write(str(angle) + "\t") resultsFile.write(str(hDistance) + "\t") resultsFile.write(str(distance) + "\t") resultsFile.write(str(modelIndex) + "\n") resultsFile.close()