def calc_vecsum(structure,metalName,valenceDictionary): # print(valenceDictionary.keys()) metals = ["FE", "CO", "MN", "CU", "NI", "MO","W", "V"] atoms = list(structure.get_atoms()) metalRow = get_metalRow(list(structure.get_atoms()),metalName) metalAtom = atoms[metalRow] numAtoms = len(atoms) vecsum = 0 fij = PDB.Vector(x=0,y=0,z=0) for idx in range(0,numAtoms): if idx != metalRow: # print('blah') atomNames = metalName+"_"+atoms[idx].get_name().upper() ligandAtom = atoms[idx] distance = abs(ligandAtom - metalAtom) vec = (ligandAtom.get_vector() - metalAtom.get_vector()) rij = vec.__truediv__(distance) ligOcc = ligandAtom.get_occupancy() # print('ligOCC: ',ligOcc) # print('valence: ',valenceDictionary[atomNames]['Valence']) oxInd = valenceDictionary[atomNames]['Ox'].index(valenceDictionary['oxNum']) bondValence = float(valenceDictionary[atomNames]['Valence'][oxInd]) # print('blha: ' + str(bondValence)) sij = float(ligOcc) * bondValence # print('sij',sij) # raise TypeError('somethingHappend ' + str(ij)) fij = fij.__add__(np.multiply(rij.get_array(),sij)) # print('fij: ',fij) vecsum = math.sqrt(fij.__mul__(fij)) / float(valenceDictionary['Valency']) # print('vecsum: ',vecsum) return vecsum
def calc_vecsum(metVal, ox): # print(valenceDictionary.keys()) # The borderline and outlier thresholds are >0.10 and >0.23, respectively, for nVECSUM, # >10% and >25%, respectively, for the vacancy parameter, which is the percentage of all expected coordination sites left vacant (Supplementary Fig. 2 and Supplementary Table 2). For example, ions with all coordination sites occupied by ligands (vacancy = 0) are classi- fied as acceptable. For geometry with an expected coordination number greater than four, metals with one vacant coordina- tion site (vacancy ≤ 25%) are borderline, and metals with two or more vacant coordination sites (vacancy > 25%) vecsum = 0 fij = PDB.Vector(x=0, y=0, z=0) bonds = [ key for key in metVal[ox].keys() if key not in ['coordNum', 'valence'] ] for bond in bonds: distance = metVal[ox][bond]['dist'] metVec = metVal[ox][bond]['metVec'] ligVec = metVal[ox][bond]['ligVec'] # print('metVec',metVec) # print('ligVec',ligVec) vec = (ligVec - metVec) rij = vec.__truediv__(distance) ligOcc = metVal[ox][bond]['ligOcc'] bondValence = metVal[ox][bond]['bond_val'] # print('blha: ' + str(bondValence)) sij = float(ligOcc) * bondValence # print('sij',sij) # raise TypeError('somethingHappend ' + str(ij)) fij = fij.__add__(np.multiply(rij.get_array(), sij)) # print('fij: ',fij) vecsum = math.sqrt(fij.__mul__(fij)) / metVal[ox]['valence'] # print('vecsum: ',vecsum) return vecsum
def pick_single_FPpoint(atoms, distance=20, bead_name=atom_name): """ Return the coordinates of a point distance units away from the first atom in atoms with name bead_name along a line through the COG """ cog = PDB.Vector(*centre_of_geometry(atoms)) first_bead = PDB.Vector(0, 0, 0) # Pick the first bead_name atom in atoms and read coords for atom in atoms: if atom.get_name() == bead_name: first_bead = atom.get_vector() break # Find a unit vector pointing along the line from cog to first_bead unit_vector = first_bead - cog unit_vector.normalize() # Scale the unit vector to the correct distance scaled_vector = unit_vector**distance # Add the scaled vector to the first bead to get coordinates for a # fluorophore new_vector = scaled_vector + first_bead # Convert vector to tuple coords_out = (new_vector[0], new_vector[1], new_vector[2]) return coords_out
def calc_protein_vecsum(metVal, ID, ox): # print(metVal) # {'4RT5.NI_201_1655_A.hvp.pdb': {'env': 'NI1C1N2O4', 'Valence': 0, 'Ox': 0, # 'NI_NE2': {'mElem': 'NI', 'lElem': 'N', 'Ox': [2, 3], 'bond-valence': [0.24315593231842803, 0.2644062425923594]}, # 'NI_NE2_43': {'mElem': 'NI', 'lElem': 'N', 'Ox': [2, 3], 'bond-valence': [0.41219316064853856, 0.44821626924826263]}, # 'NI_OE2': {'mElem': 'NI', 'lElem': 'O', 'Ox': [2, 3, 4], 'bond-valence': [0.22138086502773974, 0.28696034883432053, 0.3111966818850807]}, # 'NI_C2': {'mElem': 'NI', 'lElem': 'C', 'Ox': [], 'bond-valence': []}, # 'NI_O2': {'mElem': 'NI', 'lElem': 'O', 'Ox': [2, 3, 4], 'bond-valence': [0.310535384208486, 0.402525042833765, 0.43652183381558524]}, # 'NI_O3': {'mElem': 'NI', 'lElem': 'O', 'Ox': [2, 3, 4], 'bond-valence': [0.10584098720469944, 0.1371941816444871, 0.14878144062458418]}, # 'NI_O': {'mElem': 'NI', 'lElem': 'O', 'Ox': [2, 3, 4], 'bond-valence': [0.08400752496077941, 0.10889300963040541, 0.1180899849582612]}}} # print(valenceDictionary.keys()) # The borderline and outlier thresholds are >0.10 and >0.23, respectively, for nVECSUM, # >10% and >25%, respectively, for the vacancy parameter, which is the percentage of all expected coordination sites left vacant (Supplementary Fig. 2 and Supplementary Table 2). For example, ions with all coordination sites occupied by ligands (vacancy = 0) are classi- fied as acceptable. For geometry with an expected coordination number greater than four, metals with one vacant coordina- tion site (vacancy ≤ 25%) are borderline, and metals with two or more vacant coordination sites (vacancy > 25%) vecsum = 0 fij = PDB.Vector(x=0, y=0, z=0) # print(metVal[ID].keys()) bonds = [ key for key in metVal[ID].keys() if key not in ['env', 'Valence', 'Ox', 'coordNum'] ] # print(bonds) # oxInd = metVal[ID]['Ox'].index(ox) for bond in bonds: # print(ox) oxInd = metVal[ID][bond]['Ox'].index(ox) # print(oxInd) distance = metVal[ID][bond]['dist'] # print(distance) metVec = metVal[ID][bond]['metVec'] # print(metVec) ligVec = metVal[ID][bond]['ligVec'] # print(ligVec) vec = (ligVec - metVec) # print(vec) rij = vec.__truediv__(distance) # print(rij) ligOcc = metVal[ID][bond]['ligOcc'] # print(ligOcc) bondValence = metVal[ID][bond]['bond-valence'][oxInd] # print(bondValence) # print(bondValence) # print('blha: ' + str(bondValence)) sij = float(ligOcc) * bondValence # print(sij) # print('sij',sij) # raise TypeError('somethingHappend ' + str(ij)) fij = fij.__add__(np.multiply(rij.get_array(), sij)) # print('fij: ',fij) vecsum = math.sqrt(fij.__mul__(fij)) / metVal[ID]['Valence'] # print('vecsum: ',vecsum) return vecsum
def rotate_throught_bond(bond, angle, rotated_atoms, atoms_fixed): # Obtain the axis that we want to use as reference for the rotation vector = bond.getCoords()[0] - bond.getCoords()[1] vector = bio.Vector(vector) # Obtain the rotation matrix for the vector (axis) and the angle (theta) rot_mat = bio.rotaxis(angle, vector) new_coords = [] for coords in rotated_atoms.getCoords(): new_coord = np.dot(coords, rot_mat) new_coords.append(new_coord) rotated_atoms.setCoords(new_coords) structure_result = atoms_fixed + rotated_atoms return structure_result
def perturbPolygonalChain(CaChain, polyCaChain, residueNrRange=range(0, 5), perturbation=[(0.1, 0.2, 0.3), (0.1, 0.2, 0.3), (0.1, 0.2, 0.3), (0.1, 0.2, 0.3), (0.1, 0.2, 0.3)]): '''Perturbs the input chain: perturbs the residues with numbers in the provided range, residueNrRange, added to the number of the first residue in the chain; the perturbation amounts is given in 3d coords (x,y,z) in units of Å. Obs: only residues in the chain having with indices in the residueNrRange will be perturbed; in particular, if no such indices exist the chain will not be perturbed. Input: as output from getPolygonalChain. Output: perturbed chain of CAs, corresponding polygonal chain.''' perChain = {} perPolyCaChain = {} segNrRange = {} for chain in CaChain.keys(): resNr = 0 perNr = 0 perChain[chain] = [] for c in CaChain[chain]: if resNr in residueNrRange: perC = PDB.Vector.__add__(c, PDB.Vector(perturbation[perNr])) perChain[chain].append(perC) perNr += 1 else: perChain[chain].append(c) resNr += 1 #derive the corresponding polygonal chain: perPolyCaChain[chain] = [] CaCnt = 0 for c in perChain[chain]: Ca = c if CaCnt > 0: perPolyCaChain[chain].append([prevCa, Ca]) prevCa = Ca CaCnt += 1 #comes in handy later to have readily available the polychain segment numbers for #which the segment is perturbed: segNr = 0 segNrRange[chain] = [] print chain for s in polyCaChain[chain]: if perPolyCaChain[chain][segNr] <> s: segNrRange[chain].append(segNr) #print segNr segNr += 1 return perChain, perPolyCaChain, segNrRange
def calc_coord(self): """Return coord of base pair exclude sugar and posphate and hydrogens""" centroid = PDB.Vector(0, 0, 0) counter = 0.0 #exclude = ["O5'","C5'", "C4'", "O4'", "C3'", "O3'", "C2'", "O2'", "P", "OP2", "OP1", "OP3","C1'"] # exclude = [] for atom in self.a: if atom.name not in exclude: if not atom.name.startswith('H'): centroid = centroid + atom.get_vector() counter += 1 for atom in self.b: if atom.name not in exclude: if not atom.name.startswith('H'): centroid = centroid + atom.get_vector() counter += 1 centroid = centroid / counter self.coord = numpy.array((tuple(centroid)), 'f') return self.coord
def get_pose_constraints(Pose, MaxDist, MinPositionSeperation, SasaRadius, SasaScale, UpstreamGrep, DownstreamGrep, NeedHydrogen=True): ''' ''' # AlexsSasaCalculator is from Alex's interface_fragment_matching # thanks Alex! # # This is used to give buried polar contacts more weight. Thanks Alex Ford! try: from interface_fragment_matching.utility.analysis import AtomicSasaCalculator # make instace of Alex's sasa calculator AlexsSasaCalculator = AtomicSasaCalculator(probe_radius=SasaRadius) ResidueAtomSasa = AlexsSasaCalculator.calculate_per_atom_sasa(Pose) except ImportError: ' Error: SASA weighting of contacts requires interface_fragment_matching from Alex Ford ' # for making full atom kd tree ResAtmCoordLists = [] # for translating from kd tree index to ( residue, atom ) coord ResAtmRecordLists = [] # loop through all residue numbers for Res in range(1, Pose.n_residue() + 1): # remade for each residue AtmRecordList = [] AtmCoordList = [] # loop through residue's atom numbers for Atm in range(1, Pose.residue(Res).natoms() + 1): # add (residue, atom) coord to residue's list AtmRecordList.append((Res, Atm)) # add atom xyz coord to residue's list AtmCoordList.append( np.array(list(Pose.residue(Res).atom(Atm).xyz()))) # add residue's lists to respective global lists ResAtmCoordLists.extend(AtmCoordList) ResAtmRecordLists.extend(AtmRecordList) ResidueAtomArray = np.array(ResAtmCoordLists) ResidueAtomKDTree = spatial.KDTree(ResidueAtomArray) ResidueAtomNeighbors = ResidueAtomKDTree.query_ball_point( ResidueAtomArray, MaxDist) # ResidueAtomNearNeighbors = ResidueAtomKDTree.query_ball_point( ResidueAtomArray, 2.0 ) ResidueAtomHydrogens = ResidueAtomKDTree.query_ball_point( ResidueAtomArray, 1.1) # holds constraints before printing AllConstraints = [] # holds sorted cst AllBackboneBackboneCst = [] AllBackboneSidechainCst = [] AllSidechainSidechainCst = [] # All contacts are from upstream to downstream residues to avoid double counting Upstream = [] for UpIndex, UpXyzCoords in enumerate(ResAtmCoordLists): UpRes, UpAtm = ResAtmRecordLists[UpIndex] # # loop through residues storing info on oxygens # for UpRes in range( 1, Pose.n_residue() + 1 ): # # loop through atoms # for UpAtm in range( 1, Pose.residue(UpRes).natoms() + 1 ): UpName = Pose.residue(UpRes).atom_name(UpAtm).replace(' ', '') # skip virtual residues if Pose.residue(UpRes).is_virtual(UpAtm): continue # this guy # / # checks upstream name V if re.match(UpstreamGrep, UpName): # print '\n'*2 # print 'UpRes, UpName', UpRes, UpName # get neighbors of upstream residues NeighborsOfUpstream = ResidueAtomNeighbors[UpIndex] # prep for loop Downstreams = [] Constraints = [] BackboneBackboneCst = [] BackboneSidechainCst = [] SidechainSidechainCst = [] # ArbitrayOrderOfAtomNames = {} for DownIndex in NeighborsOfUpstream: # name presumes downstream, checks with if imediately below DownRes, DownAtm = ResAtmRecordLists[DownIndex] # checks that downstream residue is dowstream of upstream and passes min primary sequence spacing if DownRes - UpRes >= MinPositionSeperation: DownName = Pose.residue(DownRes).atom_name( DownAtm).replace(' ', '') # skip if same atom if UpRes == DownRes: if UpName == DownName: continue # skip virtual residues if Pose.residue(DownRes).is_virtual(DownAtm): continue # checks downstream name if re.match(DownstreamGrep, DownName): # print 'DownRes, DownName', DownRes, DownName PotentialUpstreamHydrogens = ResidueAtomHydrogens[ UpIndex] UpstreamHydrogens = [] # print 'PotentialUpstreamHydrogens', PotentialUpstreamHydrogens for UpH_I in PotentialUpstreamHydrogens: UpH_Res, UpH_Atm = ResAtmRecordLists[UpH_I] UpH_Name = Pose.residue(UpH_Res).atom_name( UpH_Atm).replace(' ', '') # print 'UpH_Name', UpH_Name if 'H' in UpH_Name: UpstreamHydrogens.append( (UpH_Res, UpH_Atm, UpH_Name)) # print 'UpstreamHydrogens', UpstreamHydrogens PotentialDownstreamHydrogens = ResidueAtomHydrogens[ DownIndex] DownstreamHydrogens = [] # print 'PotentialDownstreamHydrogens', PotentialDownstreamHydrogens for DownH_I in PotentialDownstreamHydrogens: DownH_Res, DownH_Atm = ResAtmRecordLists[DownH_I] DownH_Name = Pose.residue(DownH_Res).atom_name( DownH_Atm).replace(' ', '') # print 'DownH_Name', DownH_Name if 'H' in DownH_Name: DownstreamHydrogens.append( (DownH_Res, DownH_Atm, DownH_Name)) # print 'DownstreamHydrogens', DownstreamHydrogens # check their is at least one hydrogen in system before adding constraint if len(UpstreamHydrogens) or len( DownstreamHydrogens) or NeedHydrogen == False: # these trys / excepts seperate # backbone-backbone from # backbone-sidechain from # sidechain-sidechain interactions # # in future maybe sort into seperate lists, shouldn't rely on ResidueAtomSasa to know what is in backbone try: UpstreamSasa = ResidueAtomSasa[UpRes][UpName] DownstreamSasa = ResidueAtomSasa[DownRes][ DownName] AverageSasa = np.mean( [UpstreamSasa, DownstreamSasa]) BBBB = 1 BBSC = SCSC = 0 except KeyError: # These lines handle backbone to sidechain interactions # set weight equal to the most buried try: UpstreamSasa = ResidueAtomSasa[UpRes][ UpName] AverageSasa = SasaScale.FloorSasa BBSC = 1 BBBB = SCSC = 0 except KeyError: try: DownstreamSasa = ResidueAtomSasa[ DownRes][DownName] AverageSasa = SasaScale.FloorSasa BBSC = 1 BBBB = SCSC = 0 # set weight of side chain side chain equal to the most buried except KeyError: AverageSasa = SasaScale.CeilingSasa SCSC = 1 BBSC = BBBB = 0 # use instance of sasa_scale to calculate weight based on avg sasa of N and O SasaBasedWeight = SasaScale.weigh(AverageSasa) # print # print 'AverageSasa', AverageSasa # print 'SasaBasedWeight', SasaBasedWeight # print 'found downstream neighbor %s'%DownName DownXyzCoords = np.array( list( Pose.residue(DownRes).atom(DownAtm).xyz())) # print 'DownRes, DownName', DownRes, DownName # print 'DownXyzCoords', DownXyzCoords # ## Get neighbors for angles and torsions to use with AtomPairs SelectUpNeighbors = [] # iterates through upstream atom neighbors for references for angle for UpNeighborIndex in NeighborsOfUpstream: UpNeighborRes, UpNeighborAtm = ResAtmRecordLists[ UpNeighborIndex] UpNeighborName = Pose.residue( UpNeighborRes).atom_name( UpNeighborAtm).replace(' ', '') # keep looking if neighbor is hyrdogen if 'H' in UpNeighborName: continue # skip virtual residues if Pose.residue(UpNeighborRes).is_virtual( UpNeighborAtm): continue # keep looking if neighbor is self if UpNeighborName == UpName and UpNeighborRes == UpRes: continue # keep looking if neighbor is downstream residue again if UpNeighborName == DownName and UpNeighborRes == DownRes: continue UpNeighborCoords = ResAtmCoordLists[ UpNeighborIndex] DistanceToNeighbor = solenoid_tools.vector_magnitude( UpXyzCoords - UpNeighborCoords) SelectUpNeighbors.append( (DistanceToNeighbor, UpNeighborName, UpNeighborRes, UpNeighborCoords)) # sort by distance to atom, nearest first SelectUpNeighbors.sort() UpNeighbor1Tuple = SelectUpNeighbors[0] UpNeighbor2Tuple = SelectUpNeighbors[1] # print '\n'*2 # print 'UpRes, UpName', UpRes, UpName # print 'UpstreamHydrogens', UpstreamHydrogens # print 'SelectUpNeighbors', SelectUpNeighbors # get neighbors of upstream residues NeighborsOfDownstream = ResidueAtomNeighbors[ DownIndex] SelectDownNeighbors = [] # iterates through upstream atom neighbors for references for angle for DownNeighborIndex in NeighborsOfDownstream: DownNeighborRes, DownNeighborAtm = ResAtmRecordLists[ DownNeighborIndex] DownNeighborName = Pose.residue( DownNeighborRes).atom_name( DownNeighborAtm).replace(' ', '') # keep looking if neighbor is hyrdogen if 'H' in DownNeighborName: continue # skip virtual residues if Pose.residue(DownNeighborRes).is_virtual( DownNeighborAtm): continue # keep looking if neighbor is self if DownNeighborName == DownName and DownNeighborRes == DownRes: continue # keep looking if neighbor is upstream residue if DownNeighborName == UpName and DownNeighborRes == UpRes: continue DownNeighborCoords = ResAtmCoordLists[ DownNeighborIndex] DistanceToNeighbor = solenoid_tools.vector_magnitude( DownXyzCoords - DownNeighborCoords) SelectDownNeighbors.append( (DistanceToNeighbor, DownNeighborName, DownNeighborRes, DownNeighborCoords)) # sort by distance to atom, nearest first SelectDownNeighbors.sort() DownNeighbor1Tuple = SelectDownNeighbors[0] DownNeighbor2Tuple = SelectDownNeighbors[1] # print 'DownRes, DownName', DownRes, DownName # print 'DownstreamHydrogens', DownstreamHydrogens # print 'SelectDownNeighbors', SelectDownNeighbors Distance = solenoid_tools.vector_magnitude( DownXyzCoords - UpXyzCoords) DistanceCst = 'AtomPair %s %d %s %d SCALARWEIGHTEDFUNC %f HARMONIC %.2f 1.0' % ( UpName, UpRes, DownName, DownRes, SasaBasedWeight, Distance) # Use Biopython for angle and dihedral calculations # here 'Vec' means PDB.Vector of atom's xyz coord UpstreamVec = PDB.Vector(UpXyzCoords) DownstreamVec = PDB.Vector(DownXyzCoords) UpNeighbor1Vec = PDB.Vector(UpNeighbor1Tuple[3]) UpNeighbor2Vec = PDB.Vector(UpNeighbor2Tuple[3]) DownNeighbor1Vec = PDB.Vector( DownNeighbor1Tuple[3]) DownNeighbor2Vec = PDB.Vector( DownNeighbor2Tuple[3]) Angle1 = PDB.calc_angle(UpNeighbor1Vec, UpstreamVec, DownstreamVec) AngleCst1 = 'Angle %s %d %s %d %s %d SCALARWEIGHTEDFUNC %f CIRCULARHARMONIC %.2f 0.5' % ( UpNeighbor1Tuple[1], UpNeighbor1Tuple[2], UpName, UpRes, DownName, DownRes, SasaBasedWeight, Angle1) Angle2 = PDB.calc_angle(UpstreamVec, DownstreamVec, DownNeighbor1Vec) AngleCst2 = 'Angle %s %d %s %d %s %d SCALARWEIGHTEDFUNC %f CIRCULARHARMONIC %.2f 0.5' % ( UpName, UpRes, DownName, DownRes, DownNeighbor1Tuple[1], DownNeighbor1Tuple[2], SasaBasedWeight, Angle2) Torsion1 = PDB.calc_dihedral( UpNeighbor2Vec, UpNeighbor1Vec, UpstreamVec, DownstreamVec) TorsionCst1 = 'Dihedral %s %d %s %d %s %d %s %d SCALARWEIGHTEDFUNC %f CIRCULARHARMONIC %.2f 0.5' % ( UpNeighbor2Tuple[1], UpNeighbor2Tuple[2], UpNeighbor1Tuple[1], UpNeighbor1Tuple[2], UpName, UpRes, DownName, DownRes, SasaBasedWeight, Torsion1) Torsion2 = PDB.calc_dihedral( UpNeighbor1Vec, UpstreamVec, DownstreamVec, DownNeighbor1Vec) TorsionCst2 = 'Dihedral %s %d %s %d %s %d %s %d SCALARWEIGHTEDFUNC %f CIRCULARHARMONIC %.2f 0.5' % ( UpNeighbor1Tuple[1], UpNeighbor1Tuple[2], UpName, UpRes, DownName, DownRes, DownNeighbor1Tuple[1], DownNeighbor1Tuple[2], SasaBasedWeight, Torsion2) Torsion3 = PDB.calc_dihedral( UpstreamVec, DownstreamVec, DownNeighbor1Vec, DownNeighbor2Vec) TorsionCst3 = 'Dihedral %s %d %s %d %s %d %s %d SCALARWEIGHTEDFUNC %f CIRCULARHARMONIC %.2f 0.5' % ( UpName, UpRes, DownName, DownRes, DownNeighbor1Tuple[1], DownNeighbor1Tuple[2], DownNeighbor2Tuple[1], DownNeighbor2Tuple[2], SasaBasedWeight, Torsion3) # adds constraint to running lists of constraints Constraints.extend([ DistanceCst, AngleCst1, AngleCst2, TorsionCst1, TorsionCst2, TorsionCst3 ]) if BBBB: BackboneBackboneCst.extend([ DistanceCst, AngleCst1, AngleCst2, TorsionCst1, TorsionCst2, TorsionCst3 ]) if BBSC: BackboneSidechainCst.extend([ DistanceCst, AngleCst1, AngleCst2, TorsionCst1, TorsionCst2, TorsionCst3 ]) if SCSC: SidechainSidechainCst.extend([ DistanceCst, AngleCst1, AngleCst2, TorsionCst1, TorsionCst2, TorsionCst3 ]) # else: # print 'No hydrogen!' # sys.exit() AllConstraints.extend(Constraints) AllBackboneBackboneCst.extend(BackboneBackboneCst) AllBackboneSidechainCst.extend(BackboneSidechainCst) AllSidechainSidechainCst.extend(SidechainSidechainCst) SortedConstraints = (AllBackboneBackboneCst, AllBackboneSidechainCst, AllSidechainSidechainCst) return AllConstraints, SortedConstraints
numAngles = int(names.size / 4) caDistance = [] phi = [] psi = [] for i in range(0, numAngles - 2): # nIndex = 4*i; precaIndex = 4 * i + 1 cpIndex = 4 * i + 2 # oIndex = 4*i+3 nIndex = 4 * i + 4 caIndex = 4 * i + 5 cp2Index = 4 * i + 6 # o2Index =4*i+7; n2Index = 4 * i + 8 vcp = pdb.Vector(coordinates[cpIndex, 0:3]) vn = pdb.Vector(coordinates[nIndex, 0:3]) vca = pdb.Vector(coordinates[caIndex, 0:3]) vcp2 = pdb.Vector(coordinates[cp2Index, 0:3]) vn2 = pdb.Vector(coordinates[n2Index, 0:3]) alpha1 = coordinates[precaIndex, 0:3] alpha2 = coordinates[caIndex, 0:3] currentDistance = np.linalg.norm(alpha1 - alpha2) currentPhi = pdb.calc_dihedral(vcp, vn, vca, vcp2) currentPsi = pdb.calc_dihedral(vn, vca, vcp2, vn2) phi.append(currentPhi) psi.append(currentPsi) caDistance.append(currentDistance)