def calculate_residue_phi_psi_angles(prev, current, next, deg=True): """Calculate phi-psi angles for a set of three residues. Returns (phi, psi).""" phi = dihedral_angle(sites=extract_phi_sites(prev=prev, current=current), deg=deg) psi = dihedral_angle(sites=extract_psi_sites(current=current, next=next), deg=deg) return (phi, psi)
def should_be_flipped(residue_1, residue_2): """ are these residues in similar flip orientation?""" # assert residue_1.resname == residue_2.resname, "%s %s" % ( # residue_1.id_str(), residue_2.id_str()) if residue_1.resname != residue_2.resname: # e.g. 1u54, 3srv: PTR mutation of TYR residues return False if residue_1.resname in flippable_sidechains: tor_1_sites = [] for aname in flippable_sidechains[residue_1.resname][:4]: a = residue_1.find_atom_by(name=aname) if a is None: return False else: tor_1_sites.append(a.xyz) tor_23_sites = [] for aname in flippable_sidechains[residue_1.resname][:5]: a = residue_2.find_atom_by(name=aname) if a is None: return False else: tor_23_sites.append(a.xyz) tor1 = dihedral_angle( sites=tor_1_sites, deg=True) tor2 = dihedral_angle( sites=tor_23_sites[:4], deg=True) tor3 = dihedral_angle( sites=tor_23_sites[:3]+[tor_23_sites[4]], deg=True) if tor1 is None or tor2 is None or tor3 is None: return False return abs(tor1-tor2) > abs(tor1-tor3)+5 return False
def should_be_flipped(residue_1, residue_2): """ are these residues in similar flip orientation?""" assert residue_1.resname == residue_2.resname if residue_1.resname in flippable_sidechains: tor_1_sites = [] for aname in flippable_sidechains[residue_1.resname][:4]: a = residue_1.find_atom_by(name=aname) if a is None: return False else: tor_1_sites.append(a.xyz) tor_23_sites = [] for aname in flippable_sidechains[residue_1.resname][:5]: a = residue_2.find_atom_by(name=aname) if a is None: return False else: tor_23_sites.append(a.xyz) tor1 = dihedral_angle( sites=tor_1_sites, deg=True) tor2 = dihedral_angle( sites=tor_23_sites[:4], deg=True) tor3 = dihedral_angle( sites=tor_23_sites[:3]+[tor_23_sites[4]], deg=True) return abs(tor1-tor2) > abs(tor1-tor3)+5 return False
def get_peptide_bond_type(prev_Ca, prev_C, curr_N, curr_Ca): "Return the type of peptide bond" assert prev_Ca.name.strip() == 'CA' assert prev_C.name.strip() == 'C' assert curr_N.name.strip() == 'N' assert curr_Ca.name.strip() == 'CA' ang = dihedral_angle( sites=[a.xyz for a in (prev_Ca, prev_C, curr_N, curr_Ca)], deg=True) ang = numpy.round(ang, 2) if curr_N.parent().resname == 'PRO': cis, trans = ('PCIS', 'PTRANS') else: cis, trans = ('CIS', 'TRANS') # Use lenient angle tolerances to detect CIS or TRANS if angle_difference(a1=0, a2=ang, deg=True, abs_val=True) < 45: bond_type = cis elif angle_difference(a1=180, a2=ang, deg=True, abs_val=True) < 45: bond_type = trans else: print 'WARNING: BOND IS NOT CIS OR TRANS (angle {:7}) for link between {} and {} - DEFAULTING TO TRANS'.format( ang, prev_C.id_str(), curr_N.id_str()) bond_type = trans return bond_type
def find_third_neighbors(self, dihedral_proxies): """ Loop through dihedral angle proxies to find third neighbor Fill in neighbors.b1 with iseq and angle proxy""" for dp in dihedral_proxies: for i_test in dp.i_seqs: if (self.h_connectivity[i_test] is None and not self.hd_sel[i_test]): continue ih = i_test i1, i2, i3, i4 = dp.i_seqs if (ih == i1): i_third = i4 if (ih == i4): i_third = i1 dihedral = dihedral_angle(sites=[ self.sites_cart[i1], self.sites_cart[i2], self.sites_cart[i3], self.sites_cart[i4] ]) if dihedral is None: return dihedral_id = dp.angle_ideal delta = geometry_restraints.angle_delta_deg( angle_1=math.degrees(dihedral), angle_2=dihedral_id, periodicity=dp.periodicity) dihedral_ideal = math.degrees(dihedral) + delta b1 = {'iseq': i_third, 'dihedral_ideal': dihedral_ideal} self.h_connectivity[ih].b1 = b1 self.assign_b1_for_H_atom_groups(ih=ih, i_third=i_third)
def get_omega_value( self, omega_cdl=False, ): # # this is very poor! there needs to be a better way to check for cis- # for i, residue in enumerate(self): if i == 0: continue if omega_cdl: if len(self) == 3: if i == 1: continue else: if i == 2: continue ccn1, outl1 = get_c_ca_n(residue, return_subset=True) ccn2, outl2 = get_c_ca_n(self[i - 1], return_subset=True) ca1 = ccn1[1] n = ccn1[2] c = ccn2[0] ca2 = ccn2[1] omega_atoms = [ca1, n, c, ca2] if None in omega_atoms: return None omega = dihedral_angle(sites=[atom.xyz for atom in omega_atoms], deg=True) return omega
def add_c_terminal_oxygens_to_atom_group(ag, use_capping_hydrogens=False, append_to_end_of_model=False, c_ca_n=None, ): # # do we need ANISOU # rc = [] atom_name=' OXT' atom_element = 'O' bond_length=1.231 if use_capping_hydrogens: if ag.get_atom(atom_name.strip()): return [] atom_name=" HC " atom_element="H" bond_length=1. if ag.get_atom(atom_name.strip()): return [] if c_ca_n is not None: c, ca, n = c_ca_n else: c = ag.get_atom("C") if c is None: return ca = ag.get_atom("CA") if ca is None: return n = ag.get_atom("N") if n is None: return atom = ag.get_atom('O') dihedral = dihedral_angle(sites=[atom.xyz, c.xyz, ca.xyz, n.xyz, ], deg=True) ro2 = construct_xyz(c, bond_length, ca, 120., n, dihedral, period=2, ) oxys = [' O ', atom_name] for i in range(0,2): name = oxys[i] atom = ag.get_atom(name.strip()) if atom: pass #atom.xyz = ro2[i] else: atom = iotbx.pdb.hierarchy.atom() atom.name = name atom.element = atom_element atom.occ = c.occ atom.b = c.b atom.segid = ' '*4 atom.xyz = ro2[i] if append_to_end_of_model: chain = _add_atom_to_chain(atom, ag) rc.append(chain) else: # add the atom to the hierarchy ag.append_atom(atom) return rc
def add_side_chain_acid_hydrogens_to_atom_group( atom_group, anchors=None, configuration_index=0, bond_length=0.95, element='H', ): """Add hydrogen atoms to side-chain acid in place Args: atom_group (TYPE): Atom group anchors (None, optional): Atoms that specify the acids moeity configuration_index (int, optional): Configuration to return """ assert element in ['H', 'D'] c, o1, o2 = anchors if configuration_index >= 2: tmp = o1.name o1.name = o2.name o2.name = tmp tmp = o1 o1 = o2 o2 = tmp configuration_index = configuration_index % 2 if o2.name == ' OD2': name = ' HD2' atom = atom_group.get_atom('CB') elif o2.name == ' OE2': name = ' HE2' atom = atom_group.get_atom('CG') else: assert 0 if element == 'D': name = name.replace('H', 'D') dihedral = dihedral_angle(sites=[ atom.xyz, c.xyz, o1.xyz, o2.xyz, ], deg=True) ro2 = construct_xyz( o2, bond_length, c, 120., o1, dihedral, period=2, ) i = configuration_index atom = atom_group.get_atom(name.strip()) if atom: pass #atom.xyz = ro2[i] else: atom = new_atom_with_inheritance(name, element, ro2[i], o2) atom_group.append_atom(atom)
def get_dihedral_angle(atoms, round_coords=False): # round here is to emulate rounding when dumping to pdb, to get more # consistent result for rama outliers inside program and when calculating # from resulted pdb file. sites = [] if round_coords: for x in atoms: sites.append((round(x.xyz[0], 3), round(x.xyz[1], 3), round(x.xyz[2], 3))) else: sites = [x.xyz for x in atoms] return dihedral_angle( sites = sites, deg=True)
def get_torsion(ag1, ag2, an1, an2, limits='-180-180'): from scitbx.math import dihedral_angle atoms = _get_atoms(ag1, an1) + _get_atoms(ag2, an2) omega = dihedral_angle(sites=[atom.xyz for atom in atoms], deg=True) if limits == '-180-180': if omega > 180: print(omega, limits) assert 0 elif limits == '0-360': if omega < 0: omega += 360 # for atom in atoms: print atom.quote() return omega
def add_main_chain_o_to_atom_group(ag, c_ca_n=None): # cetral functuon if c_ca_n is not None: c, ca, n = c_ca_n else: c = ag.get_atom("C") if c is None: return ca = ag.get_atom("CA") if ca is None: return n = ag.get_atom("N") if n is None: return atom = ag.get_atom('O') dihedral = dihedral_angle(sites=[ atom.xyz, c.xyz, ca.xyz, n.xyz, ], deg=True) ro2 = construct_xyz( c, bond_length, ca, 120., n, dihedral, period=2, ) oxys = [' O ', atom_name] for i in range(0, 2): name = oxys[i] atom = ag.get_atom(name.strip()) if atom: pass #atom.xyz = ro2[i] else: atom = iotbx.pdb.hierarchy.atom() atom.name = name atom.element = atom_element atom.occ = c.occ atom.b = c.b atom.segid = ' ' * 4 atom.xyz = ro2[i] if append_to_end_of_model: chain = _add_atom_to_chain(atom, ag) rc.append(chain) else: # add the atom to the hierarchy ag.append_atom(atom) #for assert atom
def get_dihedral_angle(atoms, round_coords=False): # round here is to emulate rounding when dumping to pdb, to get more # consistent result for rama outliers inside program and when calculating # from resulted pdb file. if atoms is None: return None sites = [] if round_coords: for x in atoms: sites.append((round(x.xyz[0], 3), round(x.xyz[1], 3), round(x.xyz[2], 3))) else: sites = [x.xyz for x in atoms] return dihedral_angle(sites=sites, deg=True)
def check_for_plane_proxy(self, ih): neighbors = self.h_connectivity[ih] a0 = neighbors.a0['iseq'] a1 = neighbors.a1['iseq'] b1 = neighbors.b1['iseq'] if (neighbors.h1 and not neighbors.h2): # if there is only 1 H atom as second neighbor ih2 = neighbors.h1['iseq'] if ('dihedral_ideal' not in neighbors.b1 or 'dihedral_ideal' not in self.h_connectivity[ih2].b1): if ih in self.plane_h: dihedral = dihedral_angle( sites = [self.sites_cart[ih], self.sites_cart[a0], self.sites_cart[a1],self.sites_cart[b1]]) neighbors.b1['dihedral_ideal'] = math.degrees(dihedral)
def get_omega_value(residue1, residue2, verbose=False): ccn1, outl1 = get_c_ca_n(residue1, return_subset=True) ccn2, outl2 = get_c_ca_n(residue2, return_subset=True) ca1 = ccn1[1] n = ccn1[2] c = ccn2[0] ca2 = ccn2[1] omega_atoms = [ca1, n, c, ca2] if verbose: for atom in omega_atoms: print(atom.quote()) if None in omega_atoms: return None omega = dihedral_angle(sites=[atom.xyz for atom in omega_atoms], deg=True) return omega
def get_ca_dihedrals(residues, verbose=False): assert len(residues) >= 4 dihedrals = [] atoms = [] for residue in residues: atoms.append(residue.find_atom_by(name=' CA ')) if len(atoms) == 4: if verbose: print('CAs') for atom in atoms: print(atom.quote()) dihedrals.append( dihedral_angle(sites=[atom.xyz for atom in atoms], deg=True)) del atoms[0] return dihedrals
def get_phi_psi_angles(residues, verbose=False): assert len(residues) >= 3 dihedrals = [] for i in range(len(residues)): if i < 2: continue atoms = get_phi_psi_atoms(*tuple(residues[i - 2:i + 1]), verbose=verbose) if atoms is None: return None for dihedral in atoms: phi_or_psi = dihedral_angle(sites=[atom.xyz for atom in dihedral], deg=True) dihedrals.append(phi_or_psi) if verbose: print('dihedrals') for phi_or_psi in dihedrals: print('phi_or_psi', phi_or_psi) return dihedrals
def get_phi_psi_angles(self, only_psi_phi_pairs=True, force_plus_one=False, omega_cdl=False, verbose=False, ): atoms = self.get_phi_psi_atoms(only_psi_phi_pairs=only_psi_phi_pairs, force_plus_one=force_plus_one, omega_cdl=omega_cdl, ) dihedrals = [] for dihedral in atoms: phi_or_psi=dihedral_angle(sites=[atom.xyz for atom in dihedral], deg=True) dihedrals.append(phi_or_psi) if verbose: for phi_or_psi in dihedrals: print 'phi_or_psi',phi_or_psi return dihedrals
def get_phi_psi_angles(self, only_psi_phi_pairs=True, force_plus_one=False, omega_cdl=False, verbose=False, ): atoms = self.get_phi_psi_atoms(only_psi_phi_pairs=only_psi_phi_pairs, force_plus_one=force_plus_one, omega_cdl=omega_cdl, ) if atoms is None: return None dihedrals = [] for dihedral in atoms: phi_or_psi=dihedral_angle(sites=[atom.xyz for atom in dihedral], deg=True) dihedrals.append(phi_or_psi) if verbose: for phi_or_psi in dihedrals: print 'phi_or_psi',phi_or_psi return dihedrals
def cis_group(self, limit=45., verbose=False): cis_peptide_bond = False for i, residue in enumerate(self): if i==0: continue if i==2: continue # only check the middle omega angle ccn1, outl1 = get_c_ca_n(residue) ccn2, outl2 = get_c_ca_n(self[i-1]) ca1 = ccn1[1] n = ccn1[2] c = ccn2[0] ca2 = ccn2[1] omega_atoms = [ca1, n, c, ca2] omega = dihedral_angle(sites=[atom.xyz for atom in omega_atoms], deg=True) if (180.-abs(omega))>limit: cis_peptide_bond = True break if verbose: if cis_peptide_bond: print 'cis peptide bond', cis_peptide_bond, omega print self return cis_peptide_bond
def get_omega_value(self, omega_cdl=False, ): # # this is very poor! there needs to be a better way to check for cis- # for i, residue in enumerate(self): if i==0: continue if omega_cdl: if len(self)==3: if i==1: continue else: if i==2: continue ccn1, outl1 = get_c_ca_n(residue, return_subset=True) ccn2, outl2 = get_c_ca_n(self[i-1], return_subset=True) ca1 = ccn1[1] n = ccn1[2] c = ccn2[0] ca2 = ccn2[1] omega_atoms = [ca1, n, c, ca2] if None in omega_atoms: return None omega = dihedral_angle(sites=[atom.xyz for atom in omega_atoms], deg=True) return omega
def process_1_neighbor(self, neighbors): ih = neighbors.ih # if used for hydrogenate, make sure that first we use the H with dihedral angle # However, this needs some tweaking for neutron H/D situations if (neighbors.number_h_neighbors == 2): i_h1, i_h2 = neighbors.h1['iseq'], neighbors.h2['iseq'] if ('dihedral_ideal' in neighbors.b1): neighbors = self.h_connectivity[ih] elif ('dihedral_ideal' in self.h_connectivity[i_h1].b1): if self.h_parameterization[i_h1] is None: neighbors = self.h_connectivity[i_h1] elif ('dihedral_ideal' in self.h_connectivity[i_h2].b1): if self.h_parameterization[i_h2] is None: neighbors = self.h_connectivity[i_h2] ih = neighbors.ih #print(self.site_labels[ih]) i_a0 = neighbors.a0['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) if self.use_ideal_bonds_angles: disth = neighbors.a0['dist_ideal'] else: disth = (r0 - rh).length() if (not neighbors.a1 or not neighbors.b1): self.unk_list.append(ih) return i_a1 = neighbors.a1['iseq'] i_b1 = neighbors.b1['iseq'] r1 = matrix.col(self.sites_cart[i_a1]) rb1 = matrix.col(self.sites_cart[i_b1]) self.check_if_atoms_superposed(rh, r0, ih, i_a0) self.check_if_atoms_superposed(r1, r0, i_a1, i_a0) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() dihedral = dihedral_angle(sites=[ self.sites_cart[ih], self.sites_cart[i_a0], self.sites_cart[i_a1], self.sites_cart[i_b1] ]) if self.use_ideal_bonds_angles: alpha = math.radians(neighbors.a1['angle_ideal']) #allow for rotation even for idealize = True phi = dihedral if self.use_ideal_dihedral: #phi = math.radians(b1.dihedral_ideal) if 'dihedral_ideal' in neighbors.b1: phi = math.radians(neighbors.b1['dihedral_ideal']) else: alpha = (u10).angle(uh0) phi = dihedral #print(math.degrees(phi)) u1 = (r0 - r1).normalize() rb10 = rb1 - r1 # TODO check needed? u2 = (rb10 - ((rb10).dot(u1)) * u1).normalize() u3 = u1.cross(u2) if (neighbors.number_h_neighbors == 0): self.h_parameterization[ih] = riding_coefficients(htype='alg1b', ih=ih, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, b=phi, h=0, n=0, disth=disth) if (neighbors.number_h_neighbors == 2): i_h1, i_h2 = neighbors.h1['iseq'], neighbors.h2['iseq'] i_h1, i_h2 = self.check_propeller_order(i_a0=i_a0, i_a1=i_a1, ih=ih, i_h1=i_h1, i_h2=i_h2) for nprop, hprop in zip([0, 1, 2], [ih, i_h1, i_h2]): self.h_parameterization[hprop] = riding_coefficients( htype='prop', ih=hprop, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, n=nprop, b=phi, h=0, disth=disth)
def process_1_neighbor_type_arg(self, neighbors): """ alg1a: X-H2 planar groups, such as in ARG, ASN, GLN requires that dihedral angle restraint exists for at least one H atom """ ih = neighbors.ih i_h1 = neighbors.h1['iseq'] i_a0 = neighbors.a0['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) if self.use_ideal_bonds_angles: disth = neighbors.a0['dist_ideal'] else: disth = (r0 - rh).length() i_a1 = neighbors.a1['iseq'] r1 = matrix.col(self.sites_cart[i_a1]) if ('dihedral_ideal' in neighbors.b1): ih_dihedral = ih ih_no_dihedral = i_h1 else: if ('dihedral_ideal' in self.h_connectivity[i_h1].b1): ih_dihedral = i_h1 ih_no_dihedral = ih else: self.unk_list.append(ih) return i_b1 = self.h_connectivity[ih_dihedral].b1['iseq'] rb1 = matrix.col(self.sites_cart[i_b1]) # check if angle is typical for propeller # catches case of missing propeller atom if (neighbors.h1['angle_ideal'] > 107 and neighbors.h1['angle_ideal'] < 111): self.unk_list.append(ih) else: dihedral = dihedral_angle(sites=[ self.sites_cart[i_b1], self.sites_cart[i_a1], self.sites_cart[i_a0], self.sites_cart[ih_dihedral] ]) self.check_if_atoms_superposed(rh, r0, ih, i_a0) self.check_if_atoms_superposed(r1, r0, i_a1, i_a0) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() if self.use_ideal_bonds_angles: alpha = math.radians(neighbors.a1['angle_ideal']) phi = math.radians( self.h_connectivity[ih_dihedral].b1['dihedral_ideal']) else: alpha = (u10).angle(uh0) phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 # TODO check needed? u2 = (rb10 - ((rb10).dot(u10)) * u10).normalize() u3 = u1.cross(u2) for ih_alg1a, phi_alg1a in zip([ih_dihedral, ih_no_dihedral], [phi, phi + math.pi]): if self.h_parameterization[ih_alg1a] is None: self.h_parameterization[ih_alg1a] = riding_coefficients( htype='alg1a', ih=ih_alg1a, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, b=phi_alg1a, n=0, h=0, disth=disth)
def determine_H_neighbors(geometry_restraints, bond_proxies, angle_proxies, dihedral_proxies, hd_selection, sites_cart, atoms): fsc2=geometry_restraints.shell_sym_tables[2].full_simple_connectivity() fsc1=geometry_restraints.shell_sym_tables[1].full_simple_connectivity() #fsc0=geometry_restraints.shell_sym_tables[0].full_simple_connectivity() # Maybe there is better way to get number of atoms? n_atoms = len(sites_cart) connectivity = {} # loop through bond proxies to find H atom and parent atom for bproxy in bond_proxies: i_seq, j_seq = bproxy.i_seqs is_i_hd = hd_selection[i_seq] is_j_hd = hd_selection[j_seq] if(not is_i_hd and not is_j_hd): continue elif(is_i_hd and is_j_hd): assert 0 else: if (is_i_hd): ih, i_parent = i_seq, j_seq elif(is_j_hd): ih, i_parent = j_seq, i_seq else: raise Sorry("Something went wrong in bond proxies") rh = matrix.col(sites_cart[ih]) r0 = matrix.col(sites_cart[i_parent]) dist = (r0 - rh).length() parent = atom_info( iseq = i_parent, dist_ideal = bproxy.distance_ideal, dist = dist) altloc_h = atoms[ih].parent().altloc connectivity[ih]=[parent] # this is connectivity[ih][1] --> list of second non-H neighbours connectivity[ih].append([]) # this is connectivity[ih][2] --> list of second H/D neighbours connectivity[ih].append([]) # find second neighbors second_neighbors = list(fsc1[ih]) count_H = 0 altconf_dict = {} for i_second in second_neighbors: iselection = flex.size_t([ih,i_parent,i_second]) ap = angle_proxies.proxy_select( n_seq = n_atoms, iselection = iselection) # check if angle proxy exists = check that list ap is not empty if ap: altloc_i_second = atoms[i_second].parent().altloc #rint atoms[i_second].name, atoms[i_second].parent().altloc, atoms[i_second].parent().parent().resseq #ag_isecond = atoms[i_second].parent().parent().atom_groups() if ((altloc_i_second != altloc_h and altloc_i_second != 'A') and altloc_h ==''): continue neighbor = atom_info( iseq = i_second, angle_ideal = ap[0].angle_ideal) if (hd_selection[i_second]): connectivity[ih][2].append(neighbor) count_H = count_H + 1 else: connectivity[ih][1].append(neighbor) (connectivity[ih][0]).count_H = count_H # find third neighbors, if necessary if (len(connectivity[ih][1]) == 1): connectivity[ih].append([]) i_second = ((connectivity[ih][1])[0]).iseq third_neighbors = list(fsc2[ih]) third_no_dihedrals = [] for i_third in third_neighbors: if (not hd_selection[i_third]): iselection = flex.size_t([i_parent,i_second,i_third]) ap = angle_proxies.proxy_select( n_seq = n_atoms, iselection = iselection) if ap: iselection_dihe = flex.size_t([ih,i_parent,i_second,i_third]) dp = dihedral_proxies.proxy_select( n_seq = n_atoms, iselection = iselection_dihe) if dp: dihedral_id = dp[0].angle_ideal dihedral = dihedral_angle( sites=[sites_cart[i_third], sites_cart[i_second], sites_cart[i_parent],sites_cart[ih]]) sites_cart_dihe = sites_cart.select(iselection_dihe).deep_copy() delta = dp.deltas(sites_cart=sites_cart_dihe)[0] dihedral_ideal = math.degrees(dihedral) + delta neighbor = atom_info( iseq = i_third, dihedral = dihedral, dihedral_ideal = dihedral_ideal) #print dihedral_id, delta, math.degrees(dihedral), dihedral_ideal connectivity[ih][3].append(neighbor) else: neighbor = atom_info( iseq = i_third) third_no_dihedrals.append(neighbor) if (not connectivity[ih][3]): connectivity[ih][3] = third_no_dihedrals if (len(connectivity[ih][1]) == 2): reduced_neighbs = connectivity[ih][1] ix = i_parent iy = (reduced_neighbs[0]).iseq iz = (reduced_neighbs[1]).iseq iselection = flex.size_t([ix,iy,iz]) (connectivity[ih][0]).angle_ideal = angle_proxies.proxy_select( n_seq = n_atoms, iselection = iselection)[0].angle_ideal if (len(connectivity[ih][1]) == 3): # for tetrahedral, all 3 ideal angles are needed reduced_neighbs = connectivity[ih][1] angles = [] ix = i_parent _list = [(0,1),(1,2),(2,0)] for _i,_j in _list: iy = (reduced_neighbs[_i]).iseq iz = (reduced_neighbs[_j]).iseq iselection = flex.size_t([ix,iy,iz]) ap = angle_proxies.proxy_select( n_seq = n_atoms, iselection = iselection) if ap: angles.append(ap[0].angle_ideal) (connectivity[ih][0]).angle_ideal = angles return connectivity
def get_h_parameterization(h_connectivity, sites_cart, use_ideal_bonds_angles): h_parameterization = {} n_atoms = len(sites_cart) for ih in h_connectivity.keys(): #if (ih != 22): # continue #for debugging #print 'atom:', names[ih]+' ('+str(ih)+ ') residue:', \ # atoms_list[ih].resseq, 'chain', atoms_list[ih].chain_id # if entry exists already, skip it if ih in h_parameterization.keys(): continue a0 = h_connectivity[ih][0] count_H = a0.count_H reduced_neighbs = h_connectivity[ih][1] n_red_neigbs = len(reduced_neighbs) rh = matrix.col(sites_cart[ih]) r0 = matrix.col(sites_cart[a0.iseq]) if use_ideal_bonds_angles: dist_h = a0.dist_ideal else: dist_h = (r0 - rh).length() # alg2a, 2tetra, 2neigbs if (n_red_neigbs == 2): a1, a2 = reduced_neighbs[0], reduced_neighbs[1] # if H is second neighbor, gets its index if (count_H == 1): hlist = h_connectivity[ih][2] if hlist: ih2 = (hlist[0]) i_h2 = (hlist[0]).iseq else: ih2 = None sumang, a, b, h, root = get_coefficients( ih=ih, a0=a0, a1=a1, a2=a2, ih2=ih2, use_ideal_bonds_angles=use_ideal_bonds_angles, sites_cart=sites_cart, typeh='alg2') h_parameterization[ih] = parameterization_info(a0=a0.iseq, a1=a1.iseq, a2=a2.iseq, a=a, b=b, dist_h=dist_h) # alg2a if (sumang > (2 * math.pi + 0.05) and root < 0): h_parameterization[ih].htype = 'unk_ideal' elif (sumang < (2 * math.pi + 0.05) and (sumang > 2 * math.pi - 0.05)): h_parameterization[ih].htype = 'flat_2neigbs' else: if (count_H == 1): # 2 tetragonal geometry h_parameterization[ih].htype = '2tetra' h_parameterization[ih].alpha = h h_parameterization[i_h2] = parameterization_info( a0=a0.iseq, a1=a1.iseq, a2=a2.iseq, a=a, b=b, alpha=-h, dist_h=dist_h, htype='2tetra') else: # 2neigbs h_parameterization[ih].h = h h_parameterization[ih].htype = '2neigbs' # tetragonal geometry: 3neigbs elif (n_red_neigbs == 3 and count_H == 0): a1, a2, a3 = reduced_neighbs[0], reduced_neighbs[ 1], reduced_neighbs[2] a, b, h = get_coefficients_alg3( rh=rh, a0=a0, a1=a1, a2=a2, a3=a3, use_ideal_bonds_angles=use_ideal_bonds_angles, sites_cart=sites_cart) h_parameterization[ih] = parameterization_info(a0=a0.iseq, a1=a1.iseq, a2=a2.iseq, a3=a3.iseq, a=a, b=b, h=h, dist_h=dist_h, htype='3neigbs') # alg1a: X-H2 planar groups, such as in ARG, ASN, GLN # requires that dihedral angle restraint exists for at least one H atom elif (n_red_neigbs == 1 and count_H == 1 and len(h_connectivity[ih]) == 4): b1 = None a1 = reduced_neighbs[0] r1 = matrix.col(sites_cart[a1.iseq]) hlist = h_connectivity[ih][2] ih_2 = hlist[0].iseq for b1_test in h_connectivity[ih][3]: if (b1_test.dihedral_ideal is None): continue else: b1 = b1_test if (b1 == None): for b1_test in h_connectivity[ih_2][3]: if (b1_test.dihedral_ideal is None): continue else: b1 = b1_test ih, ih_2 = ih_2, ih if (b1 == None): h_parameterization[ih] = parameterization_info(htype='unk', a0=a0.iseq) continue # check if angle is typical for propeller # catches case of missing propeller atom if (hlist[0].angle_ideal > 107 and hlist[0].angle_ideal < 111): h_parameterization[ih] = parameterization_info(htype='unk', a0=a0.iseq) h_parameterization[ih_2] = parameterization_info(htype='unk', a0=a0.iseq) continue dihedral = dihedral_angle(sites=[ sites_cart[b1.iseq], sites_cart[a1.iseq], sites_cart[a0.iseq], sites_cart[ih] ]) #print 'dihedrals', a0.dihedral, dihedral, a0.dihedral_ideal rb1 = matrix.col(sites_cart[b1.iseq]) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() if use_ideal_bonds_angles: alpha = math.radians(a1.angle_ideal) phi = math.radians(b1.dihedral_ideal) #phi = dihedral else: alpha = (u10).angle(uh0) #phi = a0.dihedral phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 u2 = (rb10 - ((rb10).dot(u10)) * u10).normalize() u3 = u1.cross(u2) #print names[ih], names[b1.iseq], names[a1.iseq] if ih not in h_parameterization: h_parameterization[ih] = parameterization_info(htype='alg1a', a0=a0.iseq, a1=a1.iseq, a2=b1.iseq, phi=phi, n=0, alpha=alpha, dist_h=dist_h) if ih_2 not in h_parameterization: h_parameterization[ih_2] = parameterization_info(htype='alg1a', a0=a0.iseq, a1=a1.iseq, a2=b1.iseq, phi=phi + math.pi, n=0, alpha=alpha, dist_h=dist_h) # case 1b # a0.dihedral = dihedral angle between angle ideal and actual position elif (n_red_neigbs == 1 and (count_H == 0 or count_H == 2)): if (len(h_connectivity[ih]) != 4): continue a1 = reduced_neighbs[0] b1 = (h_connectivity[ih][3])[0] r1 = matrix.col(sites_cart[a1.iseq]) rb1 = matrix.col(sites_cart[b1.iseq]) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() dihedral = dihedral_angle(sites=[ sites_cart[ih], sites_cart[a0.iseq], sites_cart[a1.iseq], sites_cart[b1.iseq] ]) if use_ideal_bonds_angles: alpha = math.radians(a1.angle_ideal) #phi = math.radians(b1.dihedral_ideal) #allow for rotation even for idealize = True phi = dihedral else: alpha = (u10).angle(uh0) phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 u2 = (rb10 - ((rb10).dot(u1)) * u1).normalize() u3 = u1.cross(u2) h_parameterization[ih] = parameterization_info(htype='alg1b', a0=a0.iseq, a1=a1.iseq, a2=b1.iseq, phi=phi, n=0, alpha=alpha, dist_h=dist_h) if (count_H == 2): h_parameterization[ih].htype = 'prop' hlist = h_connectivity[ih][2] ih_2, ih_3 = hlist[0].iseq, hlist[1].iseq h_parameterization[ih_2] = parameterization_info(htype='prop', a0=a0.iseq, a1=a1.iseq, a2=b1.iseq, phi=phi, n=1, alpha=alpha, dist_h=dist_h) # check if order is reversed ih_2_coord = compute_H_position(sites_cart=sites_cart, ih=ih_2, hp=h_parameterization[ih_2]) h_parameterization[ih_3] = parameterization_info(htype='prop', a0=a0.iseq, a1=a1.iseq, a2=b1.iseq, phi=phi, n=2, alpha=alpha, dist_h=dist_h) if ((ih_2_coord - matrix.col(sites_cart[ih_3])).length() < (ih_2_coord - matrix.col(sites_cart[ih_2])).length()): h_parameterization[ih_2].n = 2 h_parameterization[ih_3].n = 1 else: h_parameterization[ih] = parameterization_info(htype='unk', a0=a0.iseq) return h_parameterization
def get_h_parameterization(connectivity, sites_cart, idealize): h_parameterization = {} for ih in connectivity.keys(): #for debugging #print 'atom:', names[ih]+' ('+str(ih)+ ') residue:', \ # atoms_list[ih].resseq, 'chain', atoms_list[ih].chain_id # if entry exists already, skip it if ih in h_parameterization: continue a0 = connectivity[ih][0] count_H = a0.count_H reduced_neighbs = connectivity[ih][1] n_red_neigbs = len(reduced_neighbs) rh = matrix.col(sites_cart[ih]) r0 = matrix.col(sites_cart[a0.iseq]) if idealize: dist_h = a0.dist_ideal else: dist_h = (r0 - rh).length() # alg2a, 2tetra, 2neigbs if(n_red_neigbs == 2): a1, a2 = reduced_neighbs[0], reduced_neighbs[1] # if H is second neighbor, gets its index if (count_H == 1): hlist = connectivity[ih][2] if hlist: ih2 = (hlist[0]) i_h2 = (hlist[0]).iseq else: ih2 = None sumang, a, b, h, root = get_coefficients( ih = ih, a0 = a0, a1 = a1, a2 = a2, ih2 = ih2, idealize = idealize, sites_cart = sites_cart, typeh = 'alg2') h_parameterization[ih] = parameterization_info( a0 = a0.iseq, a1 = a1.iseq, a2 = a2.iseq, a = a, b = b, dist_h = dist_h) # alg2a if (sumang > (2*math.pi + 0.05) and root < 0): h_parameterization[ih].htype = 'unk_ideal' elif (sumang < (2*math.pi + 0.05) and (sumang > 2*math.pi - 0.05)): h_parameterization[ih].htype = 'flat_2neigbs' else: if (count_H == 1): # 2 tetragonal geometry h_parameterization[ih].htype = '2tetra' h_parameterization[ih].alpha = h h_parameterization[i_h2] = parameterization_info( a0 = a0.iseq, a1 = a1.iseq, a2 = a2.iseq, a = a, b = b, alpha = -h, dist_h = dist_h, htype = '2tetra') else: # 2neigbs h_parameterization[ih].h = h h_parameterization[ih].htype = '2neigbs' # tetragonal geometry: 3neigbs elif (n_red_neigbs == 3 and count_H == 0): a1, a2, a3 = reduced_neighbs[0], reduced_neighbs[1], reduced_neighbs[2] a, b, h = get_coefficients_alg3( rh = rh, a0 = a0, a1 = a1, a2 = a2, a3 = a3, idealize = idealize, sites_cart = sites_cart) h_parameterization[ih] = parameterization_info( a0 = a0.iseq, a1 = a1.iseq, a2 = a2.iseq, a3 = a3.iseq, a = a, b = b, h = h, dist_h = dist_h, htype = '3neigbs') # alg1a: X-H2 planar groups, such as in ARG, ASN, GLN # requires that dihedral angle restraint exists elif(n_red_neigbs == 1 and count_H == 1 and len(connectivity[ih])==4): a1 = reduced_neighbs[0] r1 = matrix.col(sites_cart[a1.iseq]) hlist = connectivity[ih][2] ih_2 = hlist[0].iseq #if(len(connectivity[ih])!=4): # continue b1 = (connectivity[ih][3])[0] if (b1.dihedral_ideal == None): continue #iseq_b1 = b1.iseq dihedral = dihedral_angle( sites=[sites_cart[b1.iseq], sites_cart[a1.iseq], sites_cart[a0.iseq],sites_cart[ih]]) #print 'dihedrals', a0.dihedral, dihedral, a0.dihedral_ideal rb1 = matrix.col(sites_cart[b1.iseq]) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() if idealize: alpha = math.radians(a1.angle_ideal) phi = math.radians(b1.dihedral_ideal) #phi = dihedral else: alpha = (u10).angle(uh0) #phi = a0.dihedral phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 u2 = (rb10 - ((rb10).dot(u10)) * u10).normalize() u3 = u1.cross(u2) h_parameterization[ih] = parameterization_info( htype = 'alg1a', a0 = a0.iseq, a1 = a1.iseq, a2 = b1.iseq, phi = phi, n = 0, alpha = alpha, dist_h = dist_h) h_parameterization[ih_2] = parameterization_info( htype = 'alg1a', a0 = a0.iseq, a1 = a1.iseq, a2 = b1.iseq, phi = phi+math.pi, n = 0, alpha = alpha, dist_h = dist_h) # case 1b # a0.dihedral = dihedral angle between angle ideal and actual position elif(n_red_neigbs == 1 and (count_H == 0 or count_H ==2)): #if(count_H == 0 and len(connectivity[ih])!=4): # print 'the culprit is ', ih, names[ih], atoms_list[ih].resseq if (len(connectivity[ih])!=4): continue a1 = reduced_neighbs[0] b1 = (connectivity[ih][3])[0] r1 = matrix.col(sites_cart[a1.iseq]) rb1 = matrix.col(sites_cart[b1.iseq]) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() dihedral = dihedral_angle( sites=[sites_cart[ih], sites_cart[a0.iseq], sites_cart[a1.iseq],sites_cart[b1.iseq]]) if idealize: alpha = math.radians(a1.angle_ideal) #phi = math.radians(b1.dihedral_ideal) #allow for rotation even for idealize = True phi = dihedral else: alpha = (u10).angle(uh0) phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 u2 = (rb10 - ((rb10).dot(u1)) * u1).normalize() u3 = u1.cross(u2) h_parameterization[ih] = parameterization_info( htype = 'alg1b', a0 = a0.iseq, a1 = a1.iseq, a2 = b1.iseq, phi = phi, n = 0, alpha = alpha, dist_h = dist_h) if (count_H == 2): h_parameterization[ih].htype = 'prop' hlist = connectivity[ih][2] # TO DO: Can the order be reversed? To be kept in mind!! ih_2, ih_3 = hlist[0].iseq, hlist[1].iseq h_parameterization[ih_2] = parameterization_info( htype = 'prop', a0 = a0.iseq, a1 = a1.iseq, a2 = b1.iseq, phi = phi, n = 1, alpha = alpha, dist_h = dist_h) ih_2_coord = generate_H_positions( sites_cart = sites_cart, ih = ih_2, para_info = h_parameterization[ih_2]).rH_gen h_parameterization[ih_3] = parameterization_info( htype = 'prop', a0 = a0.iseq, a1 = a1.iseq, a2 = b1.iseq, phi = phi, n = 2, alpha = alpha, dist_h = dist_h) if ((ih_2_coord - matrix.col(sites_cart[ih_3])).length() < (ih_2_coord - matrix.col(sites_cart[ih_2])).length() ): h_parameterization[ih_2].n = 2 h_parameterization[ih_3].n = 1 else: a1 = reduced_neighbs[0] h_parameterization[ih] = parameterization_info( htype = 'unk', a0 = a0.iseq, a1 = a1.iseq) return h_parameterization
def get_dihedral_angle(atoms): from scitbx.math import dihedral_angle return dihedral_angle( sites = [x.xyz for x in atoms], deg=True)
def add_n_terminal_hydrogens_to_atom_group(ag, use_capping_hydrogens=False, append_to_end_of_model=False, retain_original_hydrogens=True, n_ca_c=None, ): rc=[] if n_ca_c is not None: n, ca, c = n_ca_c else: n = ag.get_atom("N") if n is None: return 'no N' ca = ag.get_atom("CA") if ca is None: return 'no CA' c = ag.get_atom("C") if c is None: return 'no C' atom = ag.get_atom('H') dihedral=120. if atom: dihedral = dihedral_angle(sites=[atom.xyz, n.xyz, ca.xyz, c.xyz, ], deg=True) if retain_original_hydrogens: pass else: if ag.get_atom("H"): # maybe needs to be smarter or actually work ag.remove_atom(ag.get_atom('H')) #if use_capping_hydrogens and 0: # for i, atom in enumerate(ag.atoms()): # if atom.name == ' H3 ': # ag.remove_atom(i) # break # add H1 rh3 = construct_xyz(n, 0.9, ca, 109.5, c, dihedral, ) # this could be smarter possible = ['H', 'H1', 'H2', 'H3', 'HT1', 'HT2'] h_count = 0 for h in possible: if ag.get_atom(h): h_count+=1 number_of_hydrogens=3 if use_capping_hydrogens: number_of_hydrogens-=1 #if ag.atoms()[0].parent().resname=='PRO': # number_of_hydrogens=-1 # # should name the hydrogens correctly if h_count>=number_of_hydrogens: return [] for i in range(0, number_of_hydrogens): name = " H%d " % (i+1) if retain_original_hydrogens: if i==0 and ag.get_atom('H'): continue if ag.get_atom(name.strip()): continue if ag.resname=='PRO': if i==0: continue atom = iotbx.pdb.hierarchy.atom() atom.name = name atom.element = "H" atom.xyz = rh3[i] atom.occ = n.occ atom.b = n.b atom.segid = ' '*4 if append_to_end_of_model and i+1==number_of_hydrogens: rg = _add_atom_to_chain(atom, ag) rc.append(rg) else: ag.append_atom(atom) return rc
def determine_H_neighbors(geometry_restraints, pdb_hierarchy): atoms = pdb_hierarchy.atoms() sites_cart = atoms.extract_xyz() bond_proxies_simple, asu = geometry_restraints.get_all_bond_proxies( sites_cart=sites_cart) angle_proxies = geometry_restraints.get_all_angle_proxies() dihedral_proxies = geometry_restraints.dihedral_proxies # this should be function in GRM, like previous fsc2 = geometry_restraints.shell_sym_tables[2].full_simple_connectivity() fsc1 = geometry_restraints.shell_sym_tables[1].full_simple_connectivity() #fsc0=geometry_restraints.shell_sym_tables[0].full_simple_h_connectivity() # Maybe there is better way to get number of atoms? n_atoms = len(sites_cart) h_connectivity = {} double_H = {} number_h = 0 # ------------------------------------------------------------- # loop through bond proxies to find H atom and parent atom (A0) # ------------------------------------------------------------- for bproxy in bond_proxies_simple: i_seq, j_seq = bproxy.i_seqs is_i_hd = atoms[i_seq].element_is_hydrogen() is_j_hd = atoms[j_seq].element_is_hydrogen() if (not is_i_hd and not is_j_hd): continue elif (is_i_hd and is_j_hd): assert 0 else: if (is_i_hd): ih, i_parent = i_seq, j_seq elif (is_j_hd): ih, i_parent = j_seq, i_seq else: raise Sorry("Something went wrong in bond proxies") rh = matrix.col(sites_cart[ih]) r0 = matrix.col(sites_cart[i_parent]) dist = (r0 - rh).length() parent = atom_info(iseq=i_parent, dist_ideal=bproxy.distance_ideal, dist=dist) altloc_h = atoms[ih].parent().altloc #print 'atom:', atoms[ih].name+' ('+str(ih)+ ') residue:', \ # atoms[ih].parent().parent().resseq i_parent_altloc = atoms[i_parent].parent().altloc # number_h = number_h + 1 # --------------------------------------------------------- # if entry exists already == H has two bonds # use the first atom encountered, ignore all others if (ih in h_connectivity): double_H[ih] = [(h_connectivity[ih][0]).iseq, i_parent] continue # --------------------------------------------------------- number_h = number_h + 1 # h_connectivity[ih][0] --> parent atom h_connectivity[ih] = [parent] # h_connectivity[ih][1] --> list of second non-H neighbours h_connectivity[ih].append([]) # h_connectivity[ih][2] --> list of second H/D neighbours h_connectivity[ih].append([]) # compute total list of second neighbors second_neighbors = list(fsc1[ih]) count_H = 0 altloc_dict = {} # loop to find second neighbors (ignore those where angle proxies don't # exist, and choose same altloc for all second neighbors) for i_second in second_neighbors: iselection = flex.size_t([ih, i_parent, i_second]) ap = angle_proxies.proxy_select(n_seq=n_atoms, iselection=iselection) if (ap): angle_ideal = ap[0].angle_ideal if (i_second in altloc_dict.keys()): continue altloc_dict_temp = {} i_second_altloc = atoms[i_second].parent().altloc # make sure that all second neighbors belong to same altloc if (h_connectivity[ih][1] and atoms[ (h_connectivity[ih][1])[0].iseq].parent().altloc != ''): iseq_previous = (h_connectivity[ih][1])[0].iseq overall_altloc = atoms[iseq_previous].parent().altloc if (i_second_altloc != '' and altloc_h == '' and i_second_altloc != overall_altloc): continue # if no previous altloc, chose that which has highest occ elif (i_second_altloc != '' and altloc_h == '' and i_parent_altloc != i_second_altloc): altloc_dict_temp = make_altloc_dict( atoms=atoms, index=i_second, altloc_dict_temp=altloc_dict_temp, neighbors=second_neighbors, altloc=i_second_altloc) if (i_second in altloc_dict_temp.keys()): i_second = max(altloc_dict_temp, key=lambda k: altloc_dict_temp[k]) iselection = flex.size_t([ih, i_parent, i_second]) ap = angle_proxies.proxy_select(n_seq=n_atoms, iselection=iselection) if ap: angle_ideal = ap[0].angle_ideal altloc_dict.update(altloc_dict_temp) neighbor = atom_info(iseq=i_second, angle_ideal=angle_ideal) is_same_hd = is_same_element(iseq1=ih, iseq2=i_second, atoms=atoms) if ((atoms[i_second].element_is_hydrogen() and is_same_hd) or (atoms[i_second].element_is_hydrogen() and i_second_altloc == '')): h_connectivity[ih][2].append(neighbor) count_H = count_H + 1 elif (not atoms[i_second].element_is_hydrogen()): h_connectivity[ih][1].append(neighbor) (h_connectivity[ih][0]).count_H = count_H # --------------------------------------------------------- # find third neighbors, if necessary # --------------------------------------------------------- # possibly, code for second and third neighbors can be transformed # to a function - TODO if (len(h_connectivity[ih][1]) == 1): h_connectivity[ih].append([]) i_second = ((h_connectivity[ih][1])[0]).iseq third_neighbors = list(fsc2[ih]) altloc_dict_third = {} for i_third in third_neighbors: if (not atoms[i_third].element_is_hydrogen()): iselection = flex.size_t([i_parent, i_second, i_third]) ap = angle_proxies.proxy_select(n_seq=n_atoms, iselection=iselection) if ap: if (i_third in altloc_dict_third.keys()): continue altloc_dict_third_temp = {} i_third_altloc = atoms[i_third].parent().altloc # make sure that all third neighbors belong to the same altloc if (h_connectivity[ih][3] and atoms[(h_connectivity[ih][3] )[0].iseq].parent().altloc != ''): iseq_previous_third = ( h_connectivity[ih][3])[0].iseq overall_altloc_third = atoms[ iseq_previous_third].parent().altloc if (i_third_altloc != '' and altloc_h == '' and i_third_altloc != overall_altloc_third): continue elif (i_third_altloc != '' and altloc_h == ''): altloc_dict_third_temp = make_altloc_dict( atoms=atoms, index=i_third, altloc_dict_temp=altloc_dict_third_temp, neighbors=third_neighbors, altloc=i_third_altloc) if (i_third in altloc_dict_third_temp.keys()): i_third = max( altloc_dict_third_temp, key=lambda k: altloc_dict_third_temp[k]) altloc_dict_third.update(altloc_dict_third_temp) # get dihedral angle between H, A0, A1 and third neighbor(B1, B2) iselection_dihe = flex.size_t( [ih, i_parent, i_second, i_third]) dp = dihedral_proxies.proxy_select( n_seq=n_atoms, iselection=iselection_dihe) dihedral = dihedral_angle(sites=[ sites_cart[i_third], sites_cart[i_second], sites_cart[i_parent], sites_cart[ih] ]) sites_cart_dihe = sites_cart.select( iselection_dihe).deep_copy() if dp: dihedral_id = dp[0].angle_ideal delta = dp.deltas(sites_cart=sites_cart_dihe)[0] dihedral_ideal = math.degrees(dihedral) + delta else: dihedral_ideal = None neighbor = atom_info(iseq=i_third, dihedral=dihedral, dihedral_ideal=dihedral_ideal) h_connectivity[ih][3].append(neighbor) # get ideal angles involving parent and other non-H second neighbors n_sec_neigbs = len(h_connectivity[ih][1]) if (n_sec_neigbs == 2 or n_sec_neigbs == 3): reduced_neighbs = h_connectivity[ih][1] angles = [] ix = i_parent if (n_sec_neigbs == 2): _list = [(0, 1)] else: _list = [(0, 1), (1, 2), (2, 0)] for _i, _j in _list: iy = (reduced_neighbs[_i]).iseq iz = (reduced_neighbs[_j]).iseq iselection = flex.size_t([ix, iy, iz]) ap = angle_proxies.proxy_select(n_seq=n_atoms, iselection=iselection) if ap: angles.append(ap[0].angle_ideal) else: raise Sorry("Expected ideal angles are missing. \ Second neigbs - parent atom.") (h_connectivity[ih][0]).angle_ideal = angles # return group_args(h_connectivity=h_connectivity, double_H=double_H, number_h=number_h)
def process_1_neighbor(self, neighbors): ih = neighbors.ih i_a0 = neighbors.a0['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) if self.use_ideal_bonds_angles: disth = neighbors.a0['dist_ideal'] else: disth = (r0 - rh).length() i_a1 = neighbors.a1['iseq'] i_b1 = neighbors.b1['iseq'] r1 = matrix.col(self.sites_cart[i_a1]) rb1 = matrix.col(self.sites_cart[i_b1]) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() dihedral = dihedral_angle(sites=[ self.sites_cart[ih], self.sites_cart[i_a0], self.sites_cart[i_a1], self.sites_cart[i_b1] ]) if self.use_ideal_bonds_angles: alpha = math.radians(neighbors.a1['angle_ideal']) #allow for rotation even for idealize = True #phi = math.radians(b1.dihedral_ideal) phi = dihedral else: alpha = (u10).angle(uh0) phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 u2 = (rb10 - ((rb10).dot(u1)) * u1).normalize() u3 = u1.cross(u2) if (neighbors.number_h_neighbors == 0): self.h_parameterization[ih] = riding_coefficients(htype='alg1b', ih=ih, a0=i_a0, a1=i_a1, a2=i_b1, a3=0, a=alpha, b=phi, h=0, n=0, disth=disth) if (neighbors.number_h_neighbors == 2): i_h1, i_h2 = neighbors.h1['iseq'], neighbors.h2['iseq'] i_h1, i_h2 = self.check_propeller_order(i_a0=i_a0, i_a1=i_a1, ih=ih, i_h1=i_h1, i_h2=i_h2) for nprop, hprop in zip([0, 1, 2], [ih, i_h1, i_h2]): self.h_parameterization[hprop] = riding_coefficients( htype='prop', ih=hprop, a0=i_a0, a1=i_a1, a2=i_b1, a3=0, a=alpha, n=nprop, b=phi, h=0, disth=disth)