def calc_dihedral(chain, child_res_id): """ calculates the dihedral angles (phi, psi) for residue of index child_res_id in chain returns a tuple of form (phi, psi), if it exists """ from math import pi from Bio import PDB try: CP = chain.child_list[(child_res_id-1)]['C'].get_vector() N = chain.child_list[child_res_id]['N'].get_vector() CA = chain.child_list[child_res_id]['CA'].get_vector() C = chain.child_list[child_res_id]['C'].get_vector() NA = chain.child_list[(child_res_id+1)]['N'].get_vector() except KeyError: return () # no dihedral angles for corner residues or non-a.a.'residues' else: try: phi = PDB.calc_dihedral(CP, N, CA, C)*-180/pi psi = PDB.calc_dihedral(N, CA, C, NA)*-180/pi return (phi, psi) except ZeroDivisionError: return ()
def calc_all_dihedrals(chain, child_res_id): """ calculates the dihedral angles (phi, psi, chia, chib) for residue of index child_res_id in chain returns a tuple of form (phi, psi, chia, chib), if it exists where ambiguity in chi angle definition exists: chia is in reference to the longer side chain or the heavier atom chib to the shorter if no ambiguity, chia=chib if residue is a GLY or ALA return only (phi, psi) """ from math import pi from Bio import PDB try: residue = chain.child_list[child_res_id] name = residue.get_resname() if name == 'GLY' or name == 'ALA': dih = calc_dihedral(chain, child_res_id) phi = dih[0] psi = dih[1] return (phi, psi, 0, 0) except KeyError: print "key error line 103" return () # no dihedral angles for corner residues or non-a.a.'residues' except IndexError: print 'IndexError line 106, probable cause: irregular PDB file' return () try: CP = chain.child_list[(child_res_id-1)]['C'].get_vector() N = chain.child_list[child_res_id]['N'].get_vector() CA = chain.child_list[child_res_id]['CA'].get_vector() C = chain.child_list[child_res_id]['C'].get_vector() NA = chain.child_list[(child_res_id+1)]['N'].get_vector() CB = chain.child_list[child_res_id]['CB'].get_vector() fourth_chi_atom = chain.child_list[child_res_id].child_list[5].get_vector() if name == 'VAL' or name == 'ILE' or name == 'THR': alt_fourth_chi_atom = chain.child_list[child_res_id].child_list[6].get_vector() else: alt_fourth_chi_atom = fourth_chi_atom except KeyError: print 'KeyError line 119' return () # no dihedral angles for corner residues or non-a.a.'residues' except IndexError: print 'IndexError line 122, probable cause: irregular PDB file' return () else: try: phi = PDB.calc_dihedral(CP, N, CA, C)*-180/pi psi = PDB.calc_dihedral(N, CA, C, NA)*-180/pi chia= PDB.calc_dihedral(C, CA, CB, fourth_chi_atom)*-180/pi chib= PDB.calc_dihedral(C, CA, CB, alt_fourth_chi_atom)*-180/pi return (phi, psi, chia, chib) except ZeroDivisionError: return ()
def compute_chi4(structure_, model_, chain_, curr_residue_): chi4 = 999.00 if curr_residue_.has_id('CG') and curr_residue_.has_id( 'CD') and curr_residue_.has_id('NE'): curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() curr_cd = structure_[model_.id][chain_.id][ curr_residue_.id]['CD'].get_vector() curr_ne = structure_[model_.id][chain_.id][ curr_residue_.id]['NE'].get_vector() if curr_residue_.has_id('CZ') and curr_residue_.resname == 'ARG': curr_cz = structure_[model_.id][chain_.id][ curr_residue_.id]['CZ'].get_vector() chi4 = round( math.degrees( PDB.calc_dihedral(curr_cg, curr_cd, curr_ne, curr_cz)), 2) if curr_residue_.has_id('CG') and curr_residue_.has_id( 'CD') and curr_residue_.has_id('CE'): curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() curr_cd = structure_[model_.id][chain_.id][ curr_residue_.id]['CD'].get_vector() curr_ce = structure_[model_.id][chain_.id][ curr_residue_.id]['CE'].get_vector() if curr_residue_.has_id('NZ') and curr_residue_.resname == 'LYS': curr_nz = structure_[model_.id][chain_.id][ curr_residue_.id]['NZ'].get_vector() chi4 = round( math.degrees( PDB.calc_dihedral(curr_cg, curr_cd, curr_ce, curr_nz)), 2) return chi4
def calc_dihedral(chain, child_res_id): """ calculates the dihedral angles (phi, psi) for residue of index child_res_id in chain returns a tuple of form (phi, psi), if it exists """ from math import pi from Bio import PDB try: CP = chain.child_list[(child_res_id - 1)]['C'].get_vector() N = chain.child_list[child_res_id]['N'].get_vector() CA = chain.child_list[child_res_id]['CA'].get_vector() C = chain.child_list[child_res_id]['C'].get_vector() NA = chain.child_list[(child_res_id + 1)]['N'].get_vector() except KeyError: return ( ) # no dihedral angles for corner residues or non-a.a.'residues' else: try: phi = PDB.calc_dihedral(CP, N, CA, C) * -180 / pi psi = PDB.calc_dihedral(N, CA, C, NA) * -180 / pi return (phi, psi) except ZeroDivisionError: return ()
def analyze_dihedral(self): """ Deprecated. Please use class Dihedral_Analisys """ angles = list() cov_atm_lig = self.ligand.child_dict[self.ligand_dict['cov_atm']] ##dihedral between CA < CB < SG < ligand angle_1 = math.degrees( bp.calc_dihedral(self.covalent_res.child_dict['CA'].get_vector(), self.covalent_res.child_dict['CB'].get_vector(), self.covalent_atm_res.get_vector(), cov_atm_lig.get_vector())) angles.append(angle_1) ##all dihedral of CB < SG < ligand-covalent-atom < other ligand atoms ns = bp.NeighborSearch(list(self.ligand.get_atom())) neigh = ns.search(cov_atm_lig.get_coord(), 2) neigh = filter(lambda x: x.name != self.ligand_dict['cov_atm'], neigh) # removes the atom itself for i in neigh: ang = math.degrees( bp.calc_dihedral( self.covalent_res.child_dict['CB'].get_vector(), self.covalent_atm_res.get_vector(), cov_atm_lig.get_vector(), i.get_vector())) angles.append(ang) open('/'.join([self.path, DIHEDRAL_OUTPUT]), 'w').write( reduce(lambda x, ang: ' '.join([x, str(ang)]), angles, ''))
def compute_chi1(structure_, model_, chain_, curr_residue_): chi1 = 999.00 if curr_residue_.has_id('N') and curr_residue_.has_id( 'CA') and curr_residue_.has_id('CB'): curr_n = structure_[model_.id][chain_.id][ curr_residue_.id]['N'].get_vector() curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() curr_cb = structure_[model_.id][chain_.id][ curr_residue_.id]['CB'].get_vector() if curr_residue_.has_id('CG') and (curr_residue_.resname == 'ARG' or curr_residue_.resname == 'ASN' or curr_residue_.resname == 'ASP' or curr_residue_.resname == 'GLN' or curr_residue_.resname == 'GLU' or curr_residue_.resname == 'HIS' or curr_residue_.resname == 'LEU' or curr_residue_.resname == 'LYS' or curr_residue_.resname == 'MET' or curr_residue_.resname == 'PHE' or curr_residue_.resname == 'PRO' or curr_residue_.resname == 'TRP' or curr_residue_.resname == 'TYR'): curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() chi1 = round( math.degrees( PDB.calc_dihedral(curr_n, curr_ca, curr_cb, curr_cg)), 2) if curr_residue_.has_id('SG') and curr_residue_.resname == 'CYS': curr_sg = structure_[model_.id][chain_.id][ curr_residue_.id]['SG'].get_vector() chi1 = round( math.degrees( PDB.calc_dihedral(curr_n, curr_ca, curr_cb, curr_sg)), 2) if curr_residue_.has_id('CG1') and (curr_residue_.resname == 'VAL' or curr_residue_.resname == 'ILE'): curr_cg1 = structure_[model_.id][chain_.id][ curr_residue_.id]['CG1'].get_vector() chi1 = round( math.degrees( PDB.calc_dihedral(curr_n, curr_ca, curr_cb, curr_cg1)), 2) if curr_residue_.has_id('OG') and curr_residue_.resname == 'SER': curr_og = structure_[model_.id][chain_.id][ curr_residue_.id]['OG'].get_vector() chi1 = round( math.degrees( PDB.calc_dihedral(curr_n, curr_ca, curr_cb, curr_og)), 2) if curr_residue_.has_id('OG1') and curr_residue_.resname == 'THR': curr_og1 = structure_[model_.id][chain_.id][ curr_residue_.id]['OG1'].get_vector() chi1 = round( math.degrees( PDB.calc_dihedral(curr_n, curr_ca, curr_cb, curr_og1)), 2) return chi1
def calc_phi_psi(structure): '''Function makes 3 lists of proteins C-alpha, C and N atom vectors. These lists are then used to calculate dihedral angles of proteins.''' atom_vector_list_Ca = [] atom_vector_list_N = [] atom_vector_list_C = [] # For-loop for acquiring atom vectors, but only for those residues which have a C-alpha atom. for chain in structure.get_chains(): for res in chain: if res.has_id('CA'): for atom in res: if atom.get_name() == 'N': atom_vector_list_N.append(atom.get_vector()) elif atom.get_name() == 'CA': atom_vector_list_Ca.append(atom.get_vector()) elif atom.get_name() == 'C': atom_vector_list_C.append(atom.get_vector()) else: pass len_vec = 0 ### The if statement compares vector list length between C-alpha vector list and two others, if one of them is ### shorter than C-alpha, possibly due to an error in the PDB structure, then the length vector which is ### required for calculating dihedral angles is set to be C-alpha which is the same length as other vector lists if len(atom_vector_list_Ca) > len(atom_vector_list_C) or len(atom_vector_list_Ca) > len( atom_vector_list_N): c_ca = len(atom_vector_list_Ca) - len(atom_vector_list_C) n_ca = len(atom_vector_list_Ca) - len(atom_vector_list_N) if c_ca == n_ca: len_vec = len(atom_vector_list_Ca) - c_ca else: len_vec = len(atom_vector_list_Ca) dihedral_phi = [] dihedral_psi = [] # So we don't include first amino acid which has no phi angle and last amino acid which has no psi angle! cut_off = range(1, len_vec - 1) # Calculation of phi angles! for i in cut_off: dihedral_phi.append(PDB.calc_dihedral(atom_vector_list_C[i - 1], atom_vector_list_N[i], atom_vector_list_Ca[i], atom_vector_list_C[i])) # Calculation of psi angles! for i in cut_off: dihedral_psi.append(PDB.calc_dihedral(atom_vector_list_N[i], atom_vector_list_Ca[i], atom_vector_list_C[i], atom_vector_list_N[i + 1])) return (dihedral_phi, dihedral_psi)
def calc_all_dihedrals(chain, res_id): """ calculates the dihedral angles (phi, psi, chia, chib) for residue of index res_id in chain returns a tuple of form (phi, psi, chia, chib), if it exists where ambiguity in chi angle definition exists: chia is in reference to the longer side chain or the heavier atom chib to the shorter if no ambiguity, chia=chib if residue is a GLY or ALA return only (phi, psi) """ from math import pi from Bio import PDB try: residue = chain.child_list[res_id] name = residue.get_resname() if name == 'GLY' or name == 'ALA': dih = calc_dihedral(chain, res_id) phi = dih[0] psi = dih[1] return (phi, psi, 0, 0) except KeyError: print "key error line 196" return ( ) # no dihedral angles for corner residues or non-a.a.'residues' try: CP = chain.child_list[(res_id - 1)]['C'].get_vector() N = chain.child_list[res_id]['N'].get_vector() CA = chain.child_list[res_id]['CA'].get_vector() C = chain.child_list[res_id]['C'].get_vector() NA = chain.child_list[(res_id + 1)]['N'].get_vector() CB = chain.child_list[res_id]['CB'].get_vector() fourth_chi_atom = chain.child_list[res_id].child_list[5].get_vector() if name == 'VAL' or name == 'ILE' or name == 'THR': alt_fourth_chi_atom = chain.child_list[res_id].child_list[ 6].get_vector() else: alt_fourth_chi_atom = fourth_chi_atom except KeyError: print 'key error line 211' return ( ) # no dihedral angles for corner residues or non-a.a.'residues' else: phi = PDB.calc_dihedral(CP, N, CA, C) * -180 / pi psi = PDB.calc_dihedral(N, CA, C, NA) * -180 / pi chia = PDB.calc_dihedral(C, CA, CB, fourth_chi_atom) * -180 / pi chib = PDB.calc_dihedral(C, CA, CB, alt_fourth_chi_atom) * -180 / pi return (phi, psi, chia, chib)
def get_dihedral( residue_list ): ''' returns phi and psi angles of a residue and the amino acid sidechain present residue_list - []Bio.PDB.Residue - list of 3 *hopefully* continuous residues ''' for one, two in zip( residue_list[:-1], residue_list[1:] ): if ( two.get_id()[1] - one.get_id()[1] ) != 1: raise BackboneError( "Discontinuous residues", two.get_id()[1] ) atoms = ( {"C": False}, {"N": False, "CA": False, "C": False}, {"N": False} ) for i, residue in enumerate( residue_list ): if i == 1: res_name = SeqUtils.seq1( residue.get_resname() ) if not is_aa( res_name ): raise BackboneError( "Not a valid amino acid", residue.get_id()[1] ) for atom in residue.get_unpacked_list(): if atom.name in atoms[i].keys(): atoms[i][ atom.name ] = atom.get_vector() if False in map( check_dict, atoms ): raise BackboneError( "Missing backbone atoms", residue.get_id()[1] ) dihedrals = [ PDB.calc_dihedral( atoms[0]["C"], atoms[1]["N"], atoms[1]["CA"], atoms[1]["C"] ), #phi PDB.calc_dihedral( atoms[1]["N"], atoms[1]["CA"], atoms[1]["C"], atoms[2]["N"] ) #psi ] return ( dihedrals, res_name )
def compute_chi3(structure_, model_, chain_, curr_residue_): chi3 = 999.00 if curr_residue_.has_id('CB') and curr_residue_.has_id( 'CG') and curr_residue_.has_id('CD'): curr_cb = structure_[model_.id][chain_.id][ curr_residue_.id]['CB'].get_vector() curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() curr_cd = structure_[model_.id][chain_.id][ curr_residue_.id]['CD'].get_vector() if curr_residue_.has_id('NE') and curr_residue_.resname == 'ARG': curr_ne = structure_[model_.id][chain_.id][ curr_residue_.id]['NE'].get_vector() chi3 = round( math.degrees( PDB.calc_dihedral(curr_cb, curr_cg, curr_cd, curr_ne)), 2) if curr_residue_.has_id('OE1') and (curr_residue_.resname == 'GLN' or curr_residue_.resname == 'GLU'): curr_oe1 = structure_[model_.id][chain_.id][ curr_residue_.id]['OE1'].get_vector() chi3 = round( math.degrees( PDB.calc_dihedral(curr_cb, curr_cg, curr_cd, curr_oe1)), 2) if curr_residue_.has_id('CE') and curr_residue_.resname == 'LYS': curr_ce = structure_[model_.id][chain_.id][ curr_residue_.id]['CE'].get_vector() chi3 = round( math.degrees( PDB.calc_dihedral(curr_cb, curr_cg, curr_cd, curr_ce)), 2) if curr_residue_.has_id('CB') and curr_residue_.has_id( 'CG') and curr_residue_.has_id('SD') and curr_residue_.has_id( 'CE') and curr_residue_.resname == 'MET': curr_cb = structure_[model_.id][chain_.id][ curr_residue_.id]['CB'].get_vector() curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() curr_sd = structure_[model_.id][chain_.id][ curr_residue_.id]['SD'].get_vector() curr_ce = structure_[model_.id][chain_.id][ curr_residue_.id]['CE'].get_vector() chi3 = round( math.degrees(PDB.calc_dihedral(curr_cb, curr_cg, curr_sd, curr_ce)), 2) return chi3
def _sidechain_torsions(filename, model_id): parser = PDB.PDBParser(QUIET=True) structure_id = os.path.splitext(os.path.basename(filename))[0][-4:] structure = parser.get_structure(structure_id, filename) model = structure.get_list()[model_id] torsion_list = [] for chain in model: for res in chain: # Skip heteroatoms if res.id[0] != " ": continue res_name = res.resname chis = [float('nan')] * CHI_COUNT for i, chi_res in enumerate(CHI_ATOMS): if res_name in chi_res: try: atom_list = chi_res[res_name] vec_atoms = [res[a] for a in atom_list] vectors = [a.get_vector() for a in vec_atoms] angle = PDB.calc_dihedral(*vectors) chis[i] = round(math.degrees(angle), 3) except KeyError as error: logging.info("Residue doesn't have required atoms.", res_name, res.get_list(), error) resi = "{0}{1}".format(res.id[1], res.id[2].strip()) torsion_list.append([resi, res_name, chis]) return torsion_list
def calc_dihedral(self): cb = self.cov_receptor.parent['CB'] ca = self.cov_receptor.parent['CA'] lig_cov_neoghbors = self.get_atom_neighbors(self.cov_ligand, list(self.ligand.get_atoms())) self.angles = list() ang1 = math.degrees( bp.calc_dihedral(ca.get_vector(), cb.get_vector(), self.cov_receptor.get_vector(), self.cov_ligand.get_vector())) self.angles.append(ang1) for i in lig_cov_neoghbors: ang = math.degrees( bp.calc_dihedral(cb.get_vector(), self.cov_receptor.get_vector(), self.cov_ligand.get_vector(), i.get_vector())) self.angles.append(ang)
def calc_dihedral(self): cb = self.cov_receptor.parent['CB'] ca = self.cov_receptor.parent['CA'] lig_cov_neoghbors = self.get_atom_neighbors( self.cov_ligand, list(self.ligand.get_atoms())) self.angles = list() ang1 = math.degrees( bp.calc_dihedral(ca.get_vector(), cb.get_vector(), self.cov_receptor.get_vector(), self.cov_ligand.get_vector())) self.angles.append(ang1) for i in lig_cov_neoghbors: ang = math.degrees( bp.calc_dihedral(cb.get_vector(), self.cov_receptor.get_vector(), self.cov_ligand.get_vector(), i.get_vector())) self.angles.append(ang)
def compute_torsion_angles(previous_residue, residue, next_residue): """ Little helper function, calculates the backbone phi and psi torsion angles from the given residues and returns them :param residue: The amino acid residue the torsion angles shall be computed :return: Phi and psi backbone torsion angles """ # print previous_residue.get_id()[1], residue.get_id()[1], next_residue.get_id()[1] # extract the atoms for the torsion calculation # 1.) for the phi atom_CO_0 = previous_residue['C'].get_vector() atom_N_1 = residue['N'].get_vector() atom_CA_1 = residue['CA'].get_vector() atom_CO_1 = residue['C'].get_vector() atom_N_2 = next_residue['N'].get_vector() phi_angle = PDB.calc_dihedral(atom_CO_0, atom_N_1, atom_CA_1, atom_CO_1) psi_angle = PDB.calc_dihedral(atom_N_1, atom_CA_1, atom_CO_1, atom_N_2) # convert into degrees return math.degrees(phi_angle), math.degrees(psi_angle)
def analyze_dihedral(self): """ Deprecated. Please use class Dihedral_Analisys """ angles = list() cov_atm_lig = self.ligand.child_dict[self.ligand_dict['cov_atm']] ##dihedral between CA < CB < SG < ligand angle_1 = math.degrees( bp.calc_dihedral(self.covalent_res.child_dict['CA'].get_vector(), self.covalent_res.child_dict['CB'].get_vector(), self.covalent_atm_res.get_vector(), cov_atm_lig.get_vector())) angles.append(angle_1) ##all dihedral of CB < SG < ligand-covalent-atom < other ligand atoms ns = bp.NeighborSearch(list(self.ligand.get_atom())) neigh = ns.search(cov_atm_lig.get_coord(), 2) neigh = filter(lambda x: x.name != self.ligand_dict['cov_atm'], neigh)# removes the atom itself for i in neigh: ang = math.degrees( bp.calc_dihedral(self.covalent_res.child_dict['CB'].get_vector(), self.covalent_atm_res.get_vector(), cov_atm_lig.get_vector(), i.get_vector())) angles.append(ang) open('/'.join([self.path, DIHEDRAL_OUTPUT]), 'w').write(reduce(lambda x, ang: ' '.join([x, str(ang)]), angles, ''))
def __calc_chi(self, residue, group): #Define all possible chi angles for each residue chi_atoms = self.__gen_chi_list() #Convert Needed data to appropriate formats res_atoms = PDB.Selection.unfold_entities(residue, 'A') res_name = residue.get_resname() atom_names = [] for atom in res_atoms: atom_names.append(atom.get_name()) #Gather all four atoms to calculate the angle for atom1 = res_atoms[atom_names.index(chi_atoms[group][res_name][0])].get_vector() atom2 = res_atoms[atom_names.index(chi_atoms[group][res_name][1])].get_vector() atom3 = res_atoms[atom_names.index(chi_atoms[group][res_name][2])].get_vector() atom4 = res_atoms[atom_names.index(chi_atoms[group][res_name][3])].get_vector() #Return the dihedral angle between the atoms return PDB.calc_dihedral(atom1, atom2, atom3, atom4)*(180/const.pi)
def compute_psi(structure_, model_, chain_, curr_residue_, next_residue_): psi = 999.00 if curr_residue_.has_id('N') and curr_residue_.has_id( 'CA' ) and curr_residue_.has_id('C') and next_residue_.has_id('N') and ( next_residue_.id[1] == (curr_residue_.id[1] + 1) ): #The last condition is required to make sure that the residues are consecutive curr_n = structure_[model_.id][chain_.id][ curr_residue_.id]['N'].get_vector() curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() curr_c = structure_[model_.id][chain_.id][ curr_residue_.id]['C'].get_vector() next_n = structure_[model_.id][chain_.id][ next_residue_.id]['N'].get_vector() psi = round( math.degrees(PDB.calc_dihedral(curr_n, curr_ca, curr_c, next_n)), 2) return psi
def compute_omega(structure_, model_, chain_, prev_residue_, curr_residue_): omega = 999.00 if prev_residue_.has_id('CA') and prev_residue_.has_id( 'C' ) and curr_residue_.has_id('N') and curr_residue_.has_id('CA') and ( curr_residue_.id[1] == (prev_residue_.id[1] + 1) ): #The last condition is required to make sure that the residues are consecutive prev_ca = structure_[model_.id][chain_.id][ prev_residue_.id]['CA'].get_vector() prev_c = structure_[model_.id][chain_.id][ prev_residue_.id]['C'].get_vector() curr_n = structure_[model_.id][chain_.id][ curr_residue_.id]['N'].get_vector() curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() omega = round( math.degrees(PDB.calc_dihedral(prev_ca, prev_c, curr_n, curr_ca)), 2) return omega
def get_psi(chain, residue): '''Calculate the psi torsion of a residue.''' # Get the next residue res_id = residue.get_id() next_res = chain[res_id[1] + 1] next_flag = next_res.get_id()[0] if next_flag == 'W' or next_flag.startswith('H_'): raise Exception('Hetero residue type!') # Calculate the torsion n = residue['N'].get_vector() ca = residue['CA'].get_vector() c = residue['C'].get_vector() n_next = next_res['N'].get_vector() return PDB.calc_dihedral(n, ca, c, n_next)
def get_phi(chain, residue): '''Calculate the phi torsion of a residue.''' # Get the previous residue res_id = residue.get_id() prev_res = chain[res_id[1] - 1] prev_flag = prev_res.get_id()[0] if prev_flag == 'W' or prev_flag.startswith('H_'): raise Exception('Hetero residue type!') # Calculate the torsion c_prev = prev_res['C'].get_vector() n = residue['N'].get_vector() ca = residue['CA'].get_vector() c = residue['C'].get_vector() return PDB.calc_dihedral(c_prev, n, ca, c)
def compute_phi( structure_, model_, chain_, prev_residue_, curr_residue_ ): #The original variable names can not be assigned again, therefore copies of variables are created here phi = 999.00 if prev_residue_.has_id('C') and curr_residue_.has_id( 'N' ) and curr_residue_.has_id('CA') and curr_residue_.has_id('C') and ( curr_residue_.id[1] == (prev_residue_.id[1] + 1) ): #The last condition is required to make sure that the residues are consecutive prev_c = structure_[model_.id][chain_.id][ prev_residue_.id]['C'].get_vector() curr_n = structure_[model_.id][chain_.id][ curr_residue_.id]['N'].get_vector() curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() curr_c = structure_[model_.id][chain_.id][ curr_residue_.id]['C'].get_vector() phi = round( math.degrees(PDB.calc_dihedral(prev_c, curr_n, curr_ca, curr_c)), 2) return phi
def calculate_torsion(self, fn): """Calculate side-chain torsion angles for given file""" id = os.path.splitext(os.path.basename(fn))[0] torsion_list = list() structure = self.parser.get_structure(id, fn) for model in structure: model_name = model.id for chain in model: chain_name = chain.id for res in chain: # Skip heteroatoms if res.id[0] != " ": continue res_name = res.resname if res_name in ("ALA", "GLY"): continue chi_list = [""] * len(self.chi_names) for x, chi in enumerate(self.chi_names): chi_res = self.chi_atoms[chi] try: atom_list = chi_res[res_name] except KeyError: continue try: vec_atoms = [res[a] for a in atom_list] except KeyError: chi_list[x] = float("nan") continue vectors = [a.get_vector() for a in vec_atoms] angle = PDB.calc_dihedral(*vectors) if self.degrees: angle = math.degrees(angle) chi_list[x] = angle resi = "{0}{1}".format(res.id[1], res.id[2].strip()) row = [id, model_name, chain_name, res_name, resi ] + chi_list torsion_list.append(dict(zip(self.fieldnames, row))) return torsion_list
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) print(len(phi)) print(caDistance)
def compute_chi2(structure_, model_, chain_, curr_residue_): chi2 = 999.00 if curr_residue_.has_id('CA') and curr_residue_.has_id( 'CB') and curr_residue_.has_id('CG'): curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() curr_cb = structure_[model_.id][chain_.id][ curr_residue_.id]['CB'].get_vector() curr_cg = structure_[model_.id][chain_.id][ curr_residue_.id]['CG'].get_vector() if curr_residue_.has_id('CD') and (curr_residue_.resname == 'ARG' or curr_residue_.resname == 'GLN' or curr_residue_.resname == 'GLU' or curr_residue_.resname == 'LYS' or curr_residue_.resname == 'PRO'): curr_cd = structure_[model_.id][chain_.id][ curr_residue_.id]['CD'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg, curr_cd)), 2) if curr_residue_.has_id('OD1') and (curr_residue_.resname == 'ASN' or curr_residue_.resname == 'ASP'): curr_od1 = structure_[model_.id][chain_.id][ curr_residue_.id]['OD1'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg, curr_od1)), 2) if curr_residue_.has_id('ND1') and curr_residue_.resname == 'HIS': curr_nd1 = structure_[model_.id][chain_.id][ curr_residue_.id]['ND1'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg, curr_nd1)), 2) if curr_residue_.has_id('CD1') and (curr_residue_.resname == 'LEU' or curr_residue_.resname == 'PHE' or curr_residue_.resname == 'TRP' or curr_residue_.resname == 'TYR'): curr_cd1 = structure_[model_.id][chain_.id][ curr_residue_.id]['CD1'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg, curr_cd1)), 2) if curr_residue_.has_id('SD') and curr_residue_.resname == 'MET': curr_sd = structure_[model_.id][chain_.id][ curr_residue_.id]['SD'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg, curr_sd)), 2) if curr_residue_.has_id('CA') and curr_residue_.has_id( 'CB') and curr_residue_.has_id('CG1') and curr_residue_.has_id( 'CD1') and curr_residue_.resname == 'ILE': curr_ca = structure_[model_.id][chain_.id][ curr_residue_.id]['CA'].get_vector() curr_cb = structure_[model_.id][chain_.id][ curr_residue_.id]['CB'].get_vector() curr_cg1 = structure_[model_.id][chain_.id][ curr_residue_.id]['CG1'].get_vector() curr_cd1 = structure_[model_.id][chain_.id][ curr_residue_.id]['CD1'].get_vector() chi2 = round( math.degrees( PDB.calc_dihedral(curr_ca, curr_cb, curr_cg1, curr_cd1)), 2) return chi2
def calculate_torsion_psi(current_residue, next_residue): atom1 = current_residue['N'].get_vector() atom2 = current_residue['CA'].get_vector() atom3 = current_residue['C'].get_vector() atom4 = next_residue['N'].get_vector() return PDB.calc_dihedral(atom1, atom2, atom3, atom4)
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
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
def calculate_torsion_phi(previous_residue, current_residue): atom1 = previous_residue['C'].get_vector() atom2 = current_residue['N'].get_vector() atom3 = current_residue['CA'].get_vector() atom4 = current_residue['C'].get_vector() return PDB.calc_dihedral(atom1, atom2, atom3, atom4)