def sample_angle ( i_seqs, sites_cart, map_coeffs, real_map, sigma, angle_start, params, unit_cell=None) : frac_matrix = None if (unit_cell is None) : assert (map_coeffs is not None) unit_cell = map_coeffs.unit_cell() frac_matrix = unit_cell.fractionalization_matrix() assert (params.sampling_method != "direct") or (map_coeffs is not None) from cctbx import maptbx from scitbx.matrix import rotate_point_around_axis point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=sites_cart[3], angle=-angle_start, deg=True) # TODO: present option to have point (sites_cart[3]) be generated based on idealized geometry. n_degrees = 0 densities = [] while (n_degrees < 360) : point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=point, angle=params.sampling_angle, deg=True) point_frac = unit_cell.fractionalize(site_cart=point) if (params.sampling_method == "spline") and (map_coeffs is not None) : rho = real_map.tricubic_interpolation(point_frac) elif (params.sampling_method == "linear") or (map_coeffs is None) : if (map_coeffs is None) : rho = maptbx.non_crystallographic_eight_point_interpolation( map=real_map, gridding_matrix=frac_matrix, site_cart=point) #allow_out_of_bounds=True) else : rho = real_map.eight_point_interpolation(point_frac) else : rho = map_coeffs.direct_summation_at_point( site_frac=point_frac, sigma=sigma).real densities.append(rho) n_degrees += params.sampling_angle #print densities return densities
def backrub_rotate ( sites, i_seqs_primary, primary_axis, primary_angle, secondary_axis1=None, secondary_axis2=None, secondary_angle1=None, secondary_angle2=None) : """ Performs a "backrub" move of magnitude primary_angle. Rotates the atoms in sites indexed by i_seqs_primary around primary_axis. Directly modifies sites -- does not return anything. """ from scitbx.array_family import flex from scitbx import matrix assert isinstance(primary_angle, float) assert (len(primary_axis) == 2) sites_new = flex.vec3_double() for i_seq in i_seqs_primary : xyz = matrix.rotate_point_around_axis( axis_point_1=primary_axis[0], axis_point_2=primary_axis[1], point=sites[i_seq], angle=primary_angle, deg=True) sites_new.append(xyz) sites.set_selected(i_seqs_primary, sites_new)
def torsion_search_nested ( clusters, sites_cart, last_chi_symmetric=None, increment_degrees=10) : """ Iterate over all possible sidechain Chi angle combinations. """ from scitbx.array_family import flex from scitbx.matrix import rotate_point_around_axis n_angles = len(clusters) assert (n_angles >= 1) angle_range = 180 r1 = [ifloor(-angle_range/increment_degrees)] * n_angles r2 = [iceil(angle_range/increment_degrees)] * n_angles if (last_chi_symmetric) : r1[-1] = ifloor(-90/increment_degrees) r2[-1] = iceil(90/increment_degrees) nested_loop = flex.nested_loop(begin=r1, end=r2, open_range=False) selection = clusters[0].atoms_to_rotate for angles in nested_loop: xyz_moved = sites_cart.deep_copy() for i, angle_fraction in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1 = xyz_moved[cl.axis[0]], axis_point_2 = xyz_moved[cl.axis[1]], point = xyz_moved[atom], angle = angle_fraction*increment_degrees, deg=True) xyz_moved[atom] = new_xyz yield xyz_moved
def torsion_search_nested( clusters, scorer, sites_cart): n_angles = len(clusters) print n_angles if(n_angles == 3): r1 = [-3,-7,-9] r2 = [3,7,9] elif(n_angles == 4): r1 = [-5,-5,-10,-10] r2 = [5,5,10,10] else: return nested_loop = flex.nested_loop(begin=r1, end=r2, open_range=False) selection = clusters[0].atoms_to_rotate scorer.reset(sites_cart = sites_cart, selection = selection) for angles in nested_loop: xyz_moved = sites_cart.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1 = xyz_moved[cl.axis[0]], axis_point_2 = xyz_moved[cl.axis[1]], point = xyz_moved[atom], angle = angle, deg=True) xyz_moved[atom] = new_xyz scorer.update(sites_cart = xyz_moved, selection = selection) return scorer
def torsion_search(clusters, scorer, sites_cart, start, stop, step): def generate_range(start, stop, step): assert abs(start) <= abs(stop) inc = start result = [] while abs(inc) <= abs(stop): result.append(inc) inc += step return result for i_cl, cl in enumerate(clusters): if(i_cl == 0): sites_cart_start = sites_cart.deep_copy() else: sites_cart_start = scorer.sites_cart.deep_copy() scorer.reset(sites_cart=sites_cart_start, selection=cl.selection) sites_cart_ = scorer.sites_cart.deep_copy() for angle_deg in generate_range(start=start, stop=stop, step=step): xyz_moved = sites_cart_.deep_copy() for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1 = sites_cart_[cl.axis[0]], axis_point_2 = sites_cart_[cl.axis[1]], point = sites_cart_[atom], angle = angle_deg, deg=True) xyz_moved[atom] = new_xyz scorer.update(sites_cart = xyz_moved, selection = cl.selection) return scorer
def _rotate_cablam(self, model, chain, prevresid, curresid, a1, a2, angle): inside = False O_atom = None N_atom = None C_atom = None for c in model.get_master_hierarchy().only_model().chains(): if c.id.strip() == chain.strip(): for atom in c.atoms(): if atom.name.strip() == "CA" and atom.parent().parent( ).resid() == prevresid: inside = True if atom.name.strip() == "CA" and atom.parent().parent( ).resid() == curresid: inside = False if inside and atom.name.strip() in ["N", "CA", "C", "O"]: new_xyz = rotate_point_around_axis(axis_point_1=a1.xyz, axis_point_2=a2.xyz, point=atom.xyz, angle=angle, deg=True) atom.set_xyz(new_xyz) if atom.name.strip() == "O": O_atom = atom elif atom.name.strip() == "N": N_atom = atom elif atom.name.strip() == "C": C_atom = atom model.set_sites_cart_from_hierarchy(multiply_ncs=True) return O_atom, N_atom, C_atom
def rotate_atoms_around_bond(moving_h, atom_axis_point_1, atom_axis_point_2, angle, degrees=True, direction_forward=True): # changes moving_h # print "in rotation, iseqs:", atom_axis_point_1.i_seq, atom_axis_point_2.i_seq # # find xyz based on i_seqs rotate_xyz1 = None rotate_xyz2 = None if not direction_forward: angle = -angle atoms = moving_h.atoms() for a in atoms: if a.i_seq == atom_axis_point_1.i_seq: rotate_xyz1 = a.xyz elif a.i_seq == atom_axis_point_2.i_seq: rotate_xyz2 = a.xyz # rotate stuff for a in atoms: if ((direction_forward and a.i_seq > atom_axis_point_1.i_seq) or (not direction_forward and a.i_seq < atom_axis_point_2.i_seq)): new_xyz = rotate_point_around_axis(axis_point_1=rotate_xyz1, axis_point_2=rotate_xyz2, point=a.xyz, angle=angle, deg=degrees) # let's round them # print "actually setting coordinates:", a.i_seq, a.xyz, "->", new_xyz # a.set_xyz((round(new_xyz[0], 3), round(new_xyz[1], 3), round(new_xyz[2], 3))) a.set_xyz(new_xyz)
def torsion_search_nested(clusters, scorer, sites_cart): n_angles = len(clusters) print n_angles if (n_angles == 3): r1 = [-3, -7, -9] r2 = [3, 7, 9] elif (n_angles == 4): r1 = [-5, -5, -10, -10] r2 = [5, 5, 10, 10] else: return nested_loop = flex.nested_loop(begin=r1, end=r2, open_range=False) selection = clusters[0].atoms_to_rotate scorer.reset(sites_cart=sites_cart, selection=selection) for angles in nested_loop: xyz_moved = sites_cart.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=xyz_moved[cl.axis[0]], axis_point_2=xyz_moved[cl.axis[1]], point=xyz_moved[atom], angle=angle, deg=True) xyz_moved[atom] = new_xyz scorer.update(sites_cart=xyz_moved, selection=selection) return scorer
def change_residue_rotamer_in_place(self,sites_cart, residue, m_chis, r_chis, mon_lib_srv): assert m_chis.count(None) == 0 assert r_chis.count(None) == 0 axis_and_atoms_to_rotate= \ rotatable_bonds.axes_and_atoms_aa_specific( residue=residue, mon_lib_srv=mon_lib_srv, remove_clusters_with_all_h=True, log=None) if axis_and_atoms_to_rotate is None: return assert len(m_chis) == len(axis_and_atoms_to_rotate) assert len(r_chis) >= len(m_chis) counter = 0 residue_iselection = residue.atoms().extract_i_seq() sites_cart_residue = sites_cart.select(residue_iselection) for aa in axis_and_atoms_to_rotate: axis = aa[0] atoms = aa[1] residue.atoms().set_xyz(new_xyz=sites_cart_residue) new_xyz = flex.vec3_double() angle_deg = r_chis[counter] - m_chis[counter] if angle_deg < 0: angle_deg += 360.0 for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1=sites_cart_residue[axis[0]], axis_point_2=sites_cart_residue[axis[1]], point=sites_cart_residue[atom], angle=angle_deg, deg=True) sites_cart_residue[atom] = new_xyz sites_cart = sites_cart.set_selected( residue_iselection, sites_cart_residue) counter += 1
def rotate_atoms_around_bond( moving_h, atom_axis_point_1, atom_axis_point_2, angle, degrees=True): # changes moving_h # print "in rotation, iseqs:", atom_axis_point_1.i_seq, atom_axis_point_2.i_seq # # find xyz based on i_seqs rotate_xyz1 = None rotate_xyz2 = None atoms = moving_h.atoms() for a in atoms: if a.i_seq == atom_axis_point_1.i_seq: rotate_xyz1 = a.xyz elif a.i_seq == atom_axis_point_2.i_seq: rotate_xyz2 = a.xyz # rotate stuff for a in atoms: if a.i_seq > atom_axis_point_1.i_seq: new_xyz = rotate_point_around_axis( axis_point_1=rotate_xyz1, axis_point_2=rotate_xyz2, point=a.xyz, angle=angle, deg=degrees) # let's round them # print "actually setting coordinates:", a.i_seq, a.xyz, "->", new_xyz # a.set_xyz((round(new_xyz[0], 3), round(new_xyz[1], 3), round(new_xyz[2], 3))) a.set_xyz(new_xyz)
def sample(residue, clusters, states): xyz_moved_dc = residue.atoms().extract_xyz().deep_copy() chi_angles = rotamer_manager.get_chi_angles(resname=residue.resname) print residue.resname, len(chi_angles) if(residue.resname in ["ARG","LYS"]): return None # skip: too long to run if(residue.resname in ["ALA","GLY"]): assert len(chi_angles) == 0 else: len(chi_angles) > 0 for ia, angles in enumerate(chi_angles): xyz_moved = xyz_moved_dc.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1 = xyz_moved[cl.axis[0]], axis_point_2 = xyz_moved[cl.axis[1]], point = xyz_moved[atom], angle = angle, deg=False) xyz_moved[atom] = new_xyz residue.atoms().set_xyz(xyz_moved) fl = rotamer_eval.evaluate_residue(residue = residue) assert fl != "OUTLIER" if(states is not None): states.add(sites_cart=xyz_moved) return states
def fit_rotatable( pdb_hierarchy, xray_structure, map_data, rotatable_h_selection): unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() scatterers = xray_structure.scatterers() for sel_ in rotatable_h_selection: ed_val = -1 angle = 0. angular_step = 1 axis = sel_[0] points_i_seqs = sel_[1] sites_frac_best = flex.vec3_double(len(points_i_seqs)) while angle <= 360: sites_frac_tmp = flex.vec3_double(len(points_i_seqs)) ed_val_ = 0 for i_seq, point_i_seq in enumerate(points_i_seqs): site_cart_new = rotate_point_around_axis( axis_point_1 = sites_cart[axis[0]], axis_point_2 = sites_cart[axis[1]], point = sites_cart[point_i_seq], angle = angle, deg = True) site_frac_new = unit_cell.fractionalize(site_cart_new) ed_val_ += abs(maptbx.eight_point_interpolation(map_data,site_frac_new)) sites_frac_tmp[i_seq] = site_frac_new if(ed_val_ > ed_val): ed_val = ed_val_ sites_frac_best = sites_frac_tmp.deep_copy() angle += angular_step for i_seq, point_i_seq in enumerate(points_i_seqs): scatterers[point_i_seq].site = sites_frac_best[i_seq] pdb_hierarchy.adopt_xray_structure(xray_structure)
def generate_angles_nested( clusters, residue, rotamer_eval, nested_loop, include, states=None): result = [] choices = ["ALLOWED", "FAVORED", "OUTLIER", "NONE"] for it in include: assert it in choices sites_cart = residue.atoms().extract_xyz() for angles in nested_loop: sites_cart_moved = sites_cart.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom_to_rotate in cl.atoms_to_rotate: new_site_cart = rotate_point_around_axis( axis_point_1 = sites_cart_moved[cl.axis[0]], axis_point_2 = sites_cart_moved[cl.axis[1]], point = sites_cart_moved[atom_to_rotate], angle = angle, deg = True) sites_cart_moved[atom_to_rotate] = new_site_cart residue.atoms().set_xyz(sites_cart_moved) fl = str(rotamer_eval.evaluate_residue_2(residue = residue)).strip().upper() if(fl in include): if(states is not None): states.add(sites_cart=sites_cart_moved) result.append(angles) residue.atoms().set_xyz(sites_cart) # Was changed in place, so we restore it! return result
def backrub_rotate(sites, i_seqs_primary, primary_axis, primary_angle, secondary_axis1=None, secondary_axis2=None, secondary_angle1=None, secondary_angle2=None): """ Performs a "backrub" move of magnitude primary_angle. Rotates the atoms in sites indexed by i_seqs_primary around primary_axis. Directly modifies sites -- does not return anything. """ from scitbx.array_family import flex from scitbx import matrix assert isinstance(primary_angle, float) assert (len(primary_axis) == 2) sites_new = flex.vec3_double() for i_seq in i_seqs_primary: xyz = matrix.rotate_point_around_axis(axis_point_1=primary_axis[0], axis_point_2=primary_axis[1], point=sites[i_seq], angle=primary_angle, deg=True) sites_new.append(xyz) sites.set_selected(i_seqs_primary, sites_new)
def sample(residue, clusters, states): xyz_moved_dc = residue.atoms().extract_xyz().deep_copy() chi_angles = rotamer_manager.get_chi_angles(resname=residue.resname) print(residue.resname, len(chi_angles)) if (residue.resname in ["ARG", "LYS"]): return None # skip: too long to run if (residue.resname in ["ALA", "GLY"]): assert len(chi_angles) == 0 else: len(chi_angles) > 0 for ia, angles in enumerate(chi_angles): xyz_moved = xyz_moved_dc.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=xyz_moved[cl.axis[0]], axis_point_2=xyz_moved[cl.axis[1]], point=xyz_moved[atom], angle=angle, deg=False) xyz_moved[atom] = new_xyz residue.atoms().set_xyz(xyz_moved) fl = rotamer_eval.evaluate_residue(residue=residue) assert fl != "OUTLIER" if (states is not None): states.add(sites_cart=xyz_moved) return states
def fit_rotatable(pdb_hierarchy, xray_structure, map_data, rotatable_h_selection): unit_cell = xray_structure.unit_cell() sites_cart = xray_structure.sites_cart() scatterers = xray_structure.scatterers() for sel_ in rotatable_h_selection: ed_val = -1 angle = 0. angular_step = 1 axis = sel_[0] points_i_seqs = sel_[1] sites_frac_best = flex.vec3_double(len(points_i_seqs)) while angle <= 360: sites_frac_tmp = flex.vec3_double(len(points_i_seqs)) ed_val_ = 0 for i_seq, point_i_seq in enumerate(points_i_seqs): site_cart_new = rotate_point_around_axis( axis_point_1=sites_cart[axis[0]], axis_point_2=sites_cart[axis[1]], point=sites_cart[point_i_seq], angle=angle, deg=True) site_frac_new = unit_cell.fractionalize(site_cart_new) ed_val_ += abs( maptbx.eight_point_interpolation(map_data, site_frac_new)) sites_frac_tmp[i_seq] = site_frac_new if (ed_val_ > ed_val): ed_val = ed_val_ sites_frac_best = sites_frac_tmp.deep_copy() angle += angular_step for i_seq, point_i_seq in enumerate(points_i_seqs): scatterers[point_i_seq].site = sites_frac_best[i_seq] pdb_hierarchy.adopt_xray_structure(xray_structure)
def torsion_search(clusters, scorer, sites_cart, start, stop, step): def generate_range(start, stop, step): assert abs(start) <= abs(stop) inc = start result = [] while abs(inc) <= abs(stop): result.append(inc) inc += step return result for i_cl, cl in enumerate(clusters): if (i_cl == 0): sites_cart_start = sites_cart.deep_copy() else: sites_cart_start = scorer.sites_cart.deep_copy() scorer.reset(sites_cart=sites_cart_start, selection=cl.selection) sites_cart_ = scorer.sites_cart.deep_copy() for angle_deg in generate_range(start=start, stop=stop, step=step): xyz_moved = sites_cart_.deep_copy() for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=sites_cart_[cl.axis[0]], axis_point_2=sites_cart_[cl.axis[1]], point=sites_cart_[atom], angle=angle_deg, deg=True) xyz_moved[atom] = new_xyz scorer.update(sites_cart=xyz_moved, selection=cl.selection) return scorer
def torsion_search_nested(clusters, sites_cart, last_chi_symmetric=None, increment_degrees=10): """ Iterate over all possible sidechain Chi angle combinations. """ from scitbx.array_family import flex from scitbx.matrix import rotate_point_around_axis n_angles = len(clusters) assert (n_angles >= 1) angle_range = 180 r1 = [ifloor(-angle_range / increment_degrees)] * n_angles r2 = [iceil(angle_range / increment_degrees)] * n_angles if (last_chi_symmetric): r1[-1] = ifloor(-90 / increment_degrees) r2[-1] = iceil(90 / increment_degrees) nested_loop = flex.nested_loop(begin=r1, end=r2, open_range=False) selection = clusters[0].atoms_to_rotate for angles in nested_loop: xyz_moved = sites_cart.deep_copy() for i, angle_fraction in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=xyz_moved[cl.axis[0]], axis_point_2=xyz_moved[cl.axis[1]], point=xyz_moved[atom], angle=angle_fraction * increment_degrees, deg=True) xyz_moved[atom] = new_xyz yield xyz_moved
def run(pdb_file_name): pdb_inp = iotbx.pdb.input(file_name=pdb_file_name) params = mmtbx.model.manager.get_default_pdb_interpretation_params() model = mmtbx.model.manager( model_input = pdb_inp, pdb_interpretation_params = params, build_grm = True, stop_for_unknowns = False, log = null_out()) pdb_hierarchy = model.get_hierarchy() sites_cart_dc = model.get_sites_cart().deep_copy() angle = 0. # points_i_seqs = [483] # axis = [479,482] points_i_seqs = [559] axis = [556,557] while angle <= 360: atoms_xyz_tmp = flex.vec3_double(len(points_i_seqs)) atom_xyz_new = rotate_point_around_axis( axis_point_1 = sites_cart_dc[axis[0]], axis_point_2 = sites_cart_dc[axis[1]], point = sites_cart_dc[points_i_seqs[0]], angle = angle, deg = True) print (atom_xyz_new) atoms_xyz_tmp[0] = atom_xyz_new sites_cart_dc[points_i_seqs] = atoms_xyz_tmp[0] model.set_sites_cart(sites_cart = sites_cart_dc) with open(str(angle)+".pdb", "w") as of: print (model.model_as_pdb(),file=of) angle += 30.
def fit_chi1_simple ( residue, unit_cell, target_map, rotamer_eval, sampling_angle=5) : """ For residues with only a single sidechain chi angle, we can instead sample the density at sidechain atoms directly instead of using the more opaque RSR infrastructure. (Basically this is just the Ringer method applied to the Fo-Fc map.) This is somewhat of a hack but should be more sensitive. """ from scitbx.matrix import rotate_point_around_axis residue_atoms = residue.atoms() sites_start = residue_atoms.extract_xyz().deep_copy() sc_atoms = [] c_alpha = c_beta = None assert (residue.resname in rotatable_sidechain_atoms) for atom in residue.atoms() : name = atom.name.strip() if (name in rotatable_sidechain_atoms[residue.resname]) : sc_atoms.append(atom) elif (name == "CA") : c_alpha = atom elif (name == "CB") : c_beta = atom if (len(sc_atoms) == 0) or (None in [c_alpha, c_beta]) : return False angle = 0 map_level_best = 3.0 * len(sc_atoms) sites_best = sites_start is_acceptable_cys_sg = True while (angle < 360) : map_level_sum = 0 for atom in sc_atoms : atom.xyz = rotate_point_around_axis( axis_point_1=c_alpha.xyz, axis_point_2=c_beta.xyz, point=atom.xyz, angle=sampling_angle, deg=True) site_frac = unit_cell.fractionalize(site_cart=atom.xyz) map_level = target_map.eight_point_interpolation(site_frac) map_level_sum += map_level if (residue.resname == "CYS") and (atom.name.strip() == "SG") : if (map_level < 5.0) : is_acceptable_cys_sg = False angle += sampling_angle if (not is_acceptable_cys_sg) : # always True if resname != CYS continue rotamer = rotamer_eval.evaluate_residue(residue) #print angle, map_level_sum, rotamer if (map_level_sum > map_level_best) and (rotamer != "OUTLIER") : #print "setting sites_best" sites_best = residue_atoms.extract_xyz().deep_copy() map_level_best = map_level_sum #print "RMSD:", sites_best.rms_difference(sites_start) residue_atoms.set_xyz(sites_best)
def torsion_search_nested(residue, clusters, rotamer_eval, states): n_angles = len(clusters) rid = rotamer_eval.evaluate_residue(residue=residue) xyz_moved_dc = residue.atoms().extract_xyz().deep_copy() nested_loop = [] if (n_angles == 1): for a1 in range(0, 363, 3): nested_loop.append([a1]) elif (n_angles == 2): for a1 in range(0, 370, 10): #range(0,363,3): for a2 in range(0, 370, 10): #range(0,363,3): nested_loop.append([a1, a2]) elif (n_angles == 3): for a1 in range(0, 370, 10): #range(0,365,5): for a2 in range(0, 370, 10): #range(0,365,5): for a3 in range(0, 370, 10): #range(0,365,5): nested_loop.append([a1, a2, a3]) #lif(n_angles==4): # for a1 in range(0,365,5): # for a2 in range(0,365,5): # for a3 in range(0,365,5): # for a4 in range(0,365,5): # nested_loop.append([a1, a2, a3, a4]) elif (n_angles == 4): for a1 in range(0, 370, 10): for a2 in range(0, 370, 10): for a3 in range(0, 370, 10): for a4 in range(0, 370, 10): nested_loop.append([a1, a2, a3, a4]) #elif(n_angles==4): # for a1 in range(0,365,5): # for a2 in range(0,367,7): # for a3 in range(0,369,9): # for a4 in range(0,371,11): # nested_loop.append([a1, a2, a3, a4]) else: assert 0 good = [] good_sites = [] for ia, angles in enumerate(nested_loop): xyz_moved = xyz_moved_dc.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=xyz_moved[cl.axis[0]], axis_point_2=xyz_moved[cl.axis[1]], point=xyz_moved[atom], angle=angle, deg=True) xyz_moved[atom] = new_xyz residue.atoms().set_xyz(xyz_moved) #if(rotamer_eval.evaluate_residue(residue = residue) ==rid): fl = rotamer_eval.evaluate_residue(residue=residue) if (fl != "OUTLIER" and str(fl).upper() != "NONE"): states.add(sites_cart=xyz_moved) good.append(angles) return states, good, nested_loop
def construct_fourth(resN,resCA,resC,dist,angle,dihedral,method="NCAB"): if (not None in [resN, resCA, resC]) : if (method == "NCAB"): res0 = resN res1 = resC res2 = resCA elif (method == "CNAB"): res0 = resC res1 = resN res2 = resCA a = col(res2.xyz) - col(res1.xyz) b = col(res0.xyz) - col(res1.xyz) c = a.cross(b) cmag = abs(c) if(cmag > 0.000001): c *= dist/cmag c += col(res2.xyz) d = c angledhdrl = dihedral - 90 a = col(res1.xyz) b = col(res2.xyz) # XXX is there an equivalent method for 'col'? newD = col(rotate_point_around_axis( axis_point_1=res1.xyz, axis_point_2=res2.xyz, point=d.elems, angle=angledhdrl, deg=True)) a = newD - col(res2.xyz) b = col(res1.xyz) - col(res2.xyz) c = a.cross(b) cmag = abs(c) if(cmag > 0.000001): c *= dist/cmag angledhdrl = 90 - angle; a = col(res2.xyz) c += a b = c return rotate_point_around_axis( axis_point_1=a.elems, axis_point_2=b.elems, point=newD.elems, angle=angledhdrl, deg=True) return None
def construct_fourth(resN, resCA, resC, dist, angle, dihedral, method="NCAB"): if (not None in [resN, resCA, resC]): if (method == "NCAB"): res0 = resN res1 = resC res2 = resCA elif (method == "CNAB"): res0 = resC res1 = resN res2 = resCA a = col(res2.xyz) - col(res1.xyz) b = col(res0.xyz) - col(res1.xyz) c = a.cross(b) cmag = abs(c) if (cmag > 0.000001): c *= dist / cmag c += col(res2.xyz) d = c angledhdrl = dihedral - 90 a = col(res1.xyz) b = col(res2.xyz) # XXX is there an equivalent method for 'col'? newD = col( rotate_point_around_axis(axis_point_1=res1.xyz, axis_point_2=res2.xyz, point=d.elems, angle=angledhdrl, deg=True)) a = newD - col(res2.xyz) b = col(res1.xyz) - col(res2.xyz) c = a.cross(b) cmag = abs(c) if (cmag > 0.000001): c *= dist / cmag angledhdrl = 90 - angle a = col(res2.xyz) c += a b = c return rotate_point_around_axis(axis_point_1=a.elems, axis_point_2=b.elems, point=newD.elems, angle=angledhdrl, deg=True) return None
def fit_chi1_simple(residue, unit_cell, target_map, rotamer_eval, sampling_angle=5): """ For residues with only a single sidechain chi angle, we can instead sample the density at sidechain atoms directly instead of using the more opaque RSR infrastructure. (Basically this is just the Ringer method applied to the Fo-Fc map.) This is somewhat of a hack but should be more sensitive. """ from scitbx.matrix import rotate_point_around_axis residue_atoms = residue.atoms() sites_start = residue_atoms.extract_xyz().deep_copy() sc_atoms = [] c_alpha = c_beta = None assert (residue.resname in rotatable_sidechain_atoms) for atom in residue.atoms(): name = atom.name.strip() if (name in rotatable_sidechain_atoms[residue.resname]): sc_atoms.append(atom) elif (name == "CA"): c_alpha = atom elif (name == "CB"): c_beta = atom if (len(sc_atoms) == 0) or (None in [c_alpha, c_beta]): return False angle = 0 map_level_best = 3.0 * len(sc_atoms) sites_best = sites_start is_acceptable_cys_sg = True while (angle < 360): map_level_sum = 0 for atom in sc_atoms: atom.xyz = rotate_point_around_axis(axis_point_1=c_alpha.xyz, axis_point_2=c_beta.xyz, point=atom.xyz, angle=sampling_angle, deg=True) site_frac = unit_cell.fractionalize(site_cart=atom.xyz) map_level = target_map.eight_point_interpolation(site_frac) map_level_sum += map_level if (residue.resname == "CYS") and (atom.name.strip() == "SG"): if (map_level < 5.0): is_acceptable_cys_sg = False angle += sampling_angle if (not is_acceptable_cys_sg): # always True if resname != CYS continue rotamer = rotamer_eval.evaluate_residue(residue) #print angle, map_level_sum, rotamer if (map_level_sum > map_level_best) and (rotamer != "OUTLIER"): #print "setting sites_best" sites_best = residue_atoms.extract_xyz().deep_copy() map_level_best = map_level_sum #print "RMSD:", sites_best.rms_difference(sites_start) residue_atoms.set_xyz(sites_best)
def torsion_search_nested(residue, clusters, rotamer_eval, states): n_angles = len(clusters) rid = rotamer_eval.evaluate_residue(residue = residue) xyz_moved_dc = residue.atoms().extract_xyz().deep_copy() nested_loop = [] if(n_angles==1): for a1 in range(0,370,10):#range(0, 363, 3): nested_loop.append([a1]) elif(n_angles==2): for a1 in range(0,370,10):#range(0,363,3): for a2 in range(0,370,10):#range(0,363,3): nested_loop.append([a1, a2]) elif(n_angles==3): for a1 in range(0,370,10):#range(0,365,5): for a2 in range(0,370,10):#range(0,365,5): for a3 in range(0,370,10):#range(0,365,5): nested_loop.append([a1, a2, a3]) #lif(n_angles==4): # for a1 in range(0,365,5): # for a2 in range(0,365,5): # for a3 in range(0,365,5): # for a4 in range(0,365,5): # nested_loop.append([a1, a2, a3, a4]) elif(n_angles==4): for a1 in range(0,370,10): for a2 in range(0,370,10): for a3 in range(0,370,10): for a4 in range(0,370,10): nested_loop.append([a1, a2, a3, a4]) #elif(n_angles==4): # for a1 in range(0,365,5): # for a2 in range(0,367,7): # for a3 in range(0,369,9): # for a4 in range(0,371,11): # nested_loop.append([a1, a2, a3, a4]) else: assert 0 good = [] good_sites = [] for ia, angles in enumerate(nested_loop): xyz_moved = xyz_moved_dc.deep_copy() for i, angle in enumerate(angles): cl = clusters[i] for atom in cl.atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1 = xyz_moved[cl.axis[0]], axis_point_2 = xyz_moved[cl.axis[1]], point = xyz_moved[atom], angle = angle, deg=True) xyz_moved[atom] = new_xyz residue.atoms().set_xyz(xyz_moved) #if(rotamer_eval.evaluate_residue(residue = residue) ==rid): fl = rotamer_eval.evaluate_residue(residue = residue) if(fl != "OUTLIER"): states.add(sites_cart=xyz_moved) good.append(angles) return states, good, nested_loop
def sample_angle ( i_seqs, sites_cart, map_coeffs, real_map, sigma, angle_start, params) : from scitbx.matrix import rotate_point_around_axis point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=sites_cart[3], angle=-angle_start, deg=True) n_degrees = 0 densities = [] while (n_degrees < 360) : point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=point, angle=params.sampling_angle, deg=True) point_frac = map_coeffs.unit_cell().fractionalize(site_cart=point) if (params.sampling_method == "spline") : rho = real_map.tricubic_interpolation(point_frac) elif (params.sampling_method == "linear") : rho = real_map.eight_point_interpolation(point_frac) else : rho = map_coeffs.direct_summation_at_point( site_frac=point_frac, sigma=sigma).real densities.append(rho) n_degrees += params.sampling_angle return densities
def rotate_peptide(ca1, ca2, sites_cart, selected, angle_deg): from scitbx.array_family import flex from scitbx.matrix import rotate_point_around_axis axis_point_1 = sites_cart[ca1] axis_point_2 = sites_cart[ca2] new_sites = flex.vec3_double() for i_seq in selected: xyz_new = rotate_point_around_axis( axis_point_1=sites_cart[ca1], axis_point_2=sites_cart[ca2], point=sites_cart[i_seq], angle=angle_deg, deg=True, ) new_sites.append(xyz_new) return new_sites
def exercise_rotate_point_around_axis(): from scitbx.matrix import col, rotate_point_around_axis cb = col([7.767, 5.853, 7.671]) cg = col([6.935, 5.032, 8.622]) ca = col([7.000, 7.000, 7.000]) count_unchanged = 0 for angle_i in range(-360,361,15): cg_r = col(rotate_point_around_axis( axis_point_1=ca, axis_point_2=cb, point=cg, angle=angle_i, deg=True)) assert abs(abs(cb-cg)-abs(cb-cg_r)) < 1.e-6 assert abs(abs(ca-cg)-abs(ca-cg_r)) < 1.e-6 if (angle_i in [-360,0,360]): assert abs(cg_r-cg) < 1.e-6 count_unchanged += 1 cg_r_alt = ca.rt_for_rotation_around_axis_through( point=cb, angle=angle_i, deg=True) * cg assert abs(cg_r_alt - cg_r) < 1.e-6 assert count_unchanged == 3
def exercise_rotate_point_around_axis(): from scitbx.matrix import col, rotate_point_around_axis cb = col([7.767, 5.853, 7.671]) cg = col([6.935, 5.032, 8.622]) ca = col([7.000, 7.000, 7.000]) count_unchanged = 0 for angle_i in range(-360, 361, 15): cg_r = col( rotate_point_around_axis(axis_point_1=ca, axis_point_2=cb, point=cg, angle=angle_i, deg=True)) assert abs(abs(cb - cg) - abs(cb - cg_r)) < 1.e-6 assert abs(abs(ca - cg) - abs(ca - cg_r)) < 1.e-6 if (angle_i in [-360, 0, 360]): assert abs(cg_r - cg) < 1.e-6 count_unchanged += 1 cg_r_alt = ca.rt_for_rotation_around_axis_through( point=cb, angle=angle_i, deg=True) * cg assert abs(cg_r_alt - cg_r) < 1.e-6 assert count_unchanged == 3
def flip_residue(residue, mon_lib_srv=None): if residue.resname in flippable_sidechains: from mmtbx.utils import rotatable_bonds if mon_lib_srv is None: mon_lib_srv = mmtbx.monomer_library.server.server() null_log = StringIO() tardy_model = rotatable_bonds.tardy_model_one_residue( residue=residue, mon_lib_srv=mon_lib_srv, log=null_log) if tardy_model is None: return None clusters = tardy_model.tardy_tree.cluster_manager.clusters[1:] axes = tardy_model.tardy_tree.cluster_manager.hinge_edges[1:] assert len(axes) == len(clusters) residue_atoms = residue.atoms() ctr = 0 ic = 0 axis = None while ctr < len(axes): if residue_atoms[axes[ctr][0]].name.strip().upper() == flippable_sidechains[residue.resname][1].strip().upper() and \ residue_atoms[axes[ctr][1]].name.strip().upper() == flippable_sidechains[residue.resname][2].strip().upper(): axis = axes[ctr] ic = ctr ctr += 1 atoms_to_rotate = [] for ci in clusters[ic:]: atoms_to_rotate.extend(ci) if (axis is None): return None for atom in atoms_to_rotate: new_xyz = rotate_point_around_axis( axis_point_1=residue.atoms()[axis[0]].xyz, axis_point_2=residue.atoms()[axis[1]].xyz, point=residue.atoms()[atom].xyz, angle=180.0, deg=True) residue.atoms()[atom].xyz = new_xyz
def chiral_outlier_as_kinemage(self): """ Represent a chiral volume outlier in kinemage """ from mmtbx.kinemage import kin_vec outlier_type = self.outlier_type() atoms = self.atoms_info chiral_center = atoms[0] chiral_coords = matrix.rec((chiral_center.xyz[0], chiral_center.xyz[1], chiral_center.xyz[2]),(3,1)) legs = [None] #None fills the 0 index, this indexes the same as atoms_info for atom in atoms[1:]: legs.append(matrix.rec((atom.xyz[0], atom.xyz[1], atom.xyz[2]),(3,1))) #legs need to be shortened for visual/selection clarity leg_vs = [None] for leg in legs[1:]: leg_vs.append(leg - chiral_coords) leg_ends = [None,0,0,0] shorten_by = 0.3 leg_ends[1] = legs[1] - leg_vs[1].normalize()*shorten_by leg_ends[2] = legs[2] - leg_vs[2].normalize()*shorten_by leg_ends[3] = legs[3] - leg_vs[3].normalize()*shorten_by kin_text = "" #tetrahedron is drawn for all markups kin_text += "@vectorlist {%s %s} color= yellow width= 4\n" %(chiral_center.id_str(), "lines") #draw legs from chiral center kin_text += "{%s %s: %.3f sigma} P %.3f %.3f %.3f\n" % (chiral_center.id_str(),outlier_type,self.score,chiral_coords[0],chiral_coords[1],chiral_coords[2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[1].id_str(),outlier_type,self.score,leg_ends[1][0],leg_ends[1][1],leg_ends[1][2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[2].id_str(),outlier_type,self.score,leg_ends[2][0],leg_ends[2][1],leg_ends[2][2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[3].id_str(),outlier_type,self.score,leg_ends[3][0],leg_ends[3][1],leg_ends[3][2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[1].id_str(),outlier_type,self.score,leg_ends[1][0],leg_ends[1][1],leg_ends[1][2]) kin_text += "{%s %s: %.3f sigma} P %.3f %.3f %.3f\n" % (atoms[2].id_str(),outlier_type,self.score,leg_ends[2][0],leg_ends[2][1],leg_ends[2][2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (chiral_center.id_str(),outlier_type,self.score,chiral_coords[0],chiral_coords[1],chiral_coords[2]) kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[3].id_str(),outlier_type,self.score,leg_ends[3][0],leg_ends[3][1],leg_ends[3][2]) if outlier_type == "Chiral handedness swap": #Also add an arrow to suggest mirror operation #create normal to plane of 3 legs, scale to suitable length #m = rec((1, 2, 3, 4), (2, 2)) v1 = matrix.rec((atoms[1].xyz[0]-atoms[2].xyz[0], atoms[1].xyz[1]-atoms[2].xyz[1], atoms[1].xyz[2]-atoms[2].xyz[2]), (3,1)) v2 = matrix.rec((atoms[1].xyz[0]-atoms[3].xyz[0], atoms[1].xyz[1]-atoms[3].xyz[1], atoms[1].xyz[2]-atoms[3].xyz[2]), (3,1)) norm = v1.cross(v2) norm = norm.normalize() p = matrix.rec((chiral_center.xyz[0]+norm[0], chiral_center.xyz[1]+norm[1], chiral_center.xyz[2]+norm[2]),(3,1)) arrow_text = "%s %s: %.3f sigma" % (chiral_center.id_str(), outlier_type, self.score) kin_text += kin_vec(chiral_center.id_str(), chiral_center.xyz, arrow_text, p) #Add arrowhead #Move back lone that some line and out along the atoms[1]-atoms[2] line arrow_width = 0.125 * v1.normalize() arrow_end_1 = p - 0.125*norm + arrow_width arrow_end_2 = p - 0.125*norm - arrow_width #draw second arrow rotated 90 degrees, so arrowheaad is visible from more orientations arrow_end_3 = matrix.rotate_point_around_axis( axis_point_1 = chiral_coords, axis_point_2 = p, point = arrow_end_1, angle = 90, deg = True) arrow_end_4 = matrix.rotate_point_around_axis( axis_point_1 = chiral_coords, axis_point_2 = p, point = arrow_end_2, angle = 90, deg = True) kin_text += kin_vec(arrow_text, p, outlier_type, arrow_end_1) kin_text += kin_vec(arrow_text, p, outlier_type, arrow_end_2) kin_text += kin_vec(arrow_text, p, outlier_type, arrow_end_3) kin_text += kin_vec(arrow_text, p, outlier_type, arrow_end_4) #draw balls onto atoms of greatest interest kin_text += "@balllist {%s %s} color= yellow radius= 0.15\n" %(chiral_center.id_str(), "balls") if outlier_type != 'Pseudochiral naming error': #"Chiral handedness swap" or "Tetrahedral geometry outlier" #error is located at chiral center, draw ball at chiral center of interest kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (chiral_center.id_str(),outlier_type,self.score,atoms[0].xyz[0],atoms[0].xyz[1],atoms[0].xyz[2]) else: #Pseudochiral naming error #error is probably in naming of the non-center atoms #draw balls on legs, add atomnames as labels to draw attention to naming i = 1 while i <= 3: kin_text += "{%s %s: %.3f sigma} %.3f %.3f %.3f\n" % (atoms[i].id_str(),outlier_type,self.score,leg_ends[i][0],leg_ends[i][1],leg_ends[i][2]) i+=1 kin_text += "@labellist {%s %s} color= white\n" % (chiral_center.id_str(), "labels") #needs to be a different color than balls for readability during overlap #atomnames go on atoms rather than balls to reduce overlap and increase clarity kin_text += "{ %s} %.3f %.3f %.3f\n" % (chiral_center.name.strip(),chiral_center.xyz[0],chiral_center.xyz[1],chiral_center.xyz[2]) i = 1 while i <= 3: kin_text += "{ %s} %.3f %.3f %.3f\n" % (atoms[i].name.strip(),atoms[i].xyz[0],atoms[i].xyz[1],atoms[i].xyz[2]) #leading spaces reduce overlap with the ball already drawn on labeled atom i+=1 return kin_text
def shear_rotate ( sites, i_seqs_primary1, i_seqs_primary2, i_seqs_middle, i_seqs_ca234, primary_axis1, primary_angle, secondary_axis1=None, secondary_axis2=None, secondary_axis3=None) : """ Performs a "shear" move. First, rotates the atoms in sites indexed by i_seqs_primary1 within the Calpha 1-2-3 plane (around primary_axis1). Then, rotates the atoms in sites indexed by i_seqs_primary2 within the new Calpha 2'-3'-4 plane. Finally, moves the atoms in sites indexed by i_seqs_middle to plug the middle peptide into the Calpha 2'-3' gap. Directly modifies sites -- does not return anything. """ from scitbx.array_family import flex from scitbx import matrix from sys import float_info assert isinstance(primary_angle, float) assert (len(primary_axis1) == 2) if ((i_seqs_primary1 is None) or (i_seqs_primary2 is None) or (i_seqs_middle is None)) : print "TODO set shear_rotate i_seqs automatically if not provided" return # prep for second primary rotation axis sites_start = sites.deep_copy() orig_dist = abs(matrix.col(sites_start[i_seqs_ca234[1]]) - \ matrix.col(sites_start[i_seqs_ca234[0]])) # this must be happening b/c previous shears didn't actually move atoms past # ca2 for some reason... assert (orig_dist > 3.7 and orig_dist < 3.9), \ "original ca2-ca3 distance for shear looks fishy: %.3f" % orig_dist # do first primary rotation sites_new = flex.vec3_double() for i_seq in i_seqs_primary1 : xyz = matrix.rotate_point_around_axis( axis_point_1=primary_axis1[0], axis_point_2=primary_axis1[1], point=sites[i_seq], angle=primary_angle, deg=True) sites_new.append(xyz) sites.set_selected(i_seqs_primary1, sites_new) # prep for second primary rotation axis (cont'd) ca23 = matrix.col(sites[i_seqs_ca234[1]]) - matrix.col(sites[i_seqs_ca234[0]]) ca34 = matrix.col(sites[i_seqs_ca234[2]]) - matrix.col(sites[i_seqs_ca234[1]]) normal2 = ca23.cross(ca34) ca4_normal2 = matrix.col(sites_start[i_seqs_ca234[2]]) + matrix.col(normal2) primary_axis2 = [sites_start[i_seqs_ca234[2]], ca4_normal2] # do second primary rotation: # find magnitude that best preserves original ca2-ca3 distance best_diff_orig_dist = float_info.max best_sites_new = None best_theta = None theta = -1.5 * abs(primary_angle) theta_increment = 0.1 while (theta < 1.5 * abs(primary_angle)) : ca3_new = matrix.rotate_point_around_axis( axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seqs_ca234[1]], angle=theta, deg=True) dist = abs(matrix.col(ca3_new) - matrix.col(sites[i_seqs_ca234[0]])) diff_orig_dist = abs(dist - orig_dist) if (diff_orig_dist < best_diff_orig_dist) : best_theta = theta best_diff_orig_dist = diff_orig_dist # this rotation is best so far, # so do it to the *entire* third peptide and save the result sites_new = flex.vec3_double() for i_seq in i_seqs_primary2 : xyz = matrix.rotate_point_around_axis( axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seq], angle=theta, deg=True) sites_new.append(xyz) best_sites_new = sites_new theta += theta_increment sites.set_selected(i_seqs_primary2, best_sites_new) final_dist = abs(matrix.col(sites[i_seqs_ca234[1]]) - \ matrix.col(sites[i_seqs_ca234[0]])) assert (abs(final_dist - orig_dist) < 0.1), "failed to close ca2-ca3 gap!" # plug in middle peptide by averaging the positions that result from # applying the two primary rotations to the middle peptide sites_new = flex.vec3_double() for i_seq in i_seqs_middle : xyz1 = matrix.rotate_point_around_axis( axis_point_1=primary_axis1[0], axis_point_2=primary_axis1[1], point=sites[i_seq], angle=primary_angle, deg=True) xyz2 = matrix.rotate_point_around_axis( axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seq], angle=best_theta, deg=True) xyz_avg = (matrix.col(xyz1) + matrix.col(xyz2)) / 2 sites_new.append(xyz_avg) sites.set_selected(i_seqs_middle, sites_new)
def torsion_search(residue_evaluator, cluster_evaluators, axes_and_atoms_to_rotate, rotamer_sites_cart, rotamer_id_best, residue_sites_best, params = None, rotamer_id = None, include_ca_hinge = False): if(params is None): params = torsion_search_params().extract().torsion_search params.range_start = 0 params.range_stop = 360 params.step = 1.0 rotamer_sites_cart_ = rotamer_sites_cart.deep_copy() n_clusters = len(axes_and_atoms_to_rotate) c_counter = 0 for cluster_evaluator, aa in zip(cluster_evaluators,axes_and_atoms_to_rotate): #account for CA hinge at beginning of search if include_ca_hinge and c_counter == 0: cur_range_start = -6.0 cur_range_stop = 6.0 else: cur_range_start = params.range_start cur_range_stop = params.range_stop c_counter += 1 axis = aa[0] atoms = aa[1] angle_deg_best = None angle_deg_good = None for angle_deg in generate_range(start = cur_range_start, stop = cur_range_stop, step = params.step): if(c_counter != n_clusters): if include_ca_hinge and c_counter == 1: new_xyz = flex.vec3_double() for atom in atoms: new_xyz.append(rotate_point_around_axis( axis_point_1 = rotamer_sites_cart[axis[0]], axis_point_2 = rotamer_sites_cart[axis[1]], point = rotamer_sites_cart[atom], angle = angle_deg, deg=True)) else: point_local = rotamer_sites_cart[atoms[0]] new_xyz = flex.vec3_double([rotate_point_around_axis( axis_point_1 = rotamer_sites_cart[axis[0]], axis_point_2 = rotamer_sites_cart[axis[1]], point = point_local, angle = angle_deg, deg=True)]) else: new_xyz = flex.vec3_double() for atom in atoms: new_xyz.append(rotate_point_around_axis( axis_point_1 = rotamer_sites_cart[axis[0]], axis_point_2 = rotamer_sites_cart[axis[1]], point = rotamer_sites_cart[atom], angle = angle_deg, deg=True)) if(cluster_evaluator.is_better(sites_cart = new_xyz)): if(angle_deg_best is not None and abs(abs(angle_deg_best)-abs(angle_deg))> params.min_angle_between_solutions): angle_deg_good = angle_deg_best angle_deg_best = angle_deg if(angle_deg_best is not None): for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1 = rotamer_sites_cart[axis[0]], axis_point_2 = rotamer_sites_cart[axis[1]], point = rotamer_sites_cart[atom], angle = angle_deg_best, deg=True) rotamer_sites_cart[atom] = new_xyz if(angle_deg_good is not None): for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1 = rotamer_sites_cart_[axis[0]], axis_point_2 = rotamer_sites_cart_[axis[1]], point = rotamer_sites_cart_[atom], angle = angle_deg_best, deg=True) rotamer_sites_cart_[atom] = new_xyz for rsc in [rotamer_sites_cart, rotamer_sites_cart_]: if(residue_evaluator.is_better(sites_cart = rsc)): rotamer_id_best = rotamer_id residue_sites_best = rsc.deep_copy() return residue_sites_best, rotamer_id_best
def search( self, atom_group, all_dict, m_chis, r_chis, rotamer, sites_cart_moving, xray_structure, key): include_ca_hinge = False axis_and_atoms_to_rotate, tardy_labels= \ rotatable_bonds.axes_and_atoms_aa_specific( residue=atom_group, mon_lib_srv=self.mon_lib_srv, remove_clusters_with_all_h=True, include_labels=True, log=None) if (axis_and_atoms_to_rotate is None) : print >> self.log, "Skipped %s rotamer (TARDY error)" % key return False assert len(m_chis) == len(r_chis) #exclude H-only clusters if necessary while len(axis_and_atoms_to_rotate) > len(m_chis): axis_and_atoms_to_rotate = \ axis_and_atoms_to_rotate[:-1] assert len(m_chis) == len(axis_and_atoms_to_rotate) counter = 0 residue_iselection = atom_group.atoms().extract_i_seq() cur_ca = None ca_add = None ca_axes = [] for atom in atom_group.atoms(): if atom.name == " CA ": cur_ca = atom.i_seq if cur_ca is not None: cur_c_alpha_hinges = self.c_alpha_hinges.get(cur_ca) if cur_c_alpha_hinges is not None: residue_length = len(tardy_labels) for ca_pt in cur_c_alpha_hinges[0]: residue_iselection.append(ca_pt) tardy_labels.append(self.name_hash[ca_pt][0:4]) for bb_pt in cur_c_alpha_hinges[1]: residue_iselection.append(bb_pt) tardy_labels.append(self.name_hash[bb_pt][0:4]) end_pts = (residue_length, residue_length+1) group = [] for i, value in enumerate(tardy_labels): if i not in end_pts: group.append(i) ca_add = [end_pts, group] ca_axes.append(ca_add) for ax in axis_and_atoms_to_rotate: ca_axes.append(ax) sites_cart_residue = \ sites_cart_moving.select(residue_iselection) sites_cart_residue_start = sites_cart_residue.deep_copy() selection = flex.bool( len(sites_cart_moving), residue_iselection) rev_first_atoms = [] rev_start = fit_rotamers.rotamer_evaluator( sites_cart_start = sites_cart_residue_start, unit_cell = self.unit_cell, two_mfo_dfc_map = self.target_map_data, mfo_dfc_map = self.residual_map_data) sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [' N ', ' CA ', ' C ', ' O ']: sidechain_only_iselection.append(i_seq) sites_cart_sidechain = \ sites_cart_moving.select(sidechain_only_iselection) sites_frac_residue = self.unit_cell.fractionalize(sites_cart_sidechain) sigma_cutoff = 1.0 sigma_residue = [] for rsf in sites_frac_residue: if self.target_map_data.eight_point_interpolation(rsf) < sigma_cutoff: sigma_residue.append(False) else: sigma_residue.append(True) sigma_count_start = 0 for sigma_state in sigma_residue: if sigma_state: sigma_count_start += 1 else: break for aa in axis_and_atoms_to_rotate: axis = aa[0] atoms = aa[1] new_xyz = flex.vec3_double() angle_deg = r_chis[counter] - m_chis[counter] #skip angle rotations that are close to zero if math.fabs(angle_deg) < 0.01: counter += 1 continue if angle_deg < 0: angle_deg += 360.0 for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1=sites_cart_residue[axis[0]], axis_point_2=sites_cart_residue[axis[1]], point=sites_cart_residue[atom], angle=angle_deg, deg=True) sites_cart_residue[atom] = new_xyz counter += 1 #***** TEST ***** sites_cart_moving.set_selected( residue_iselection, sites_cart_residue) cur_rotamer, cur_chis, cur_value = rotalyze.evaluate_rotamer( atom_group=atom_group, sidechain_angles=self.sa, rotamer_evaluator=self.rotamer_evaluator, rotamer_id=self.rotamer_id, all_dict=all_dict, sites_cart=sites_cart_moving) assert rotamer == cur_rotamer #**************** if len(ca_axes) == 0: eval_axes = axis_and_atoms_to_rotate else: eval_axes = ca_axes include_ca_hinge = True for i_aa, aa in enumerate(eval_axes): if(i_aa == len(eval_axes)-1): sites_aa = flex.vec3_double() for aa_ in aa[1]: sites_aa.append(sites_cart_residue[aa_]) elif i_aa == 0 and include_ca_hinge: sites_aa = flex.vec3_double() for aa_ in aa[1]: sites_aa.append(sites_cart_residue[aa_]) else: sites_aa = flex.vec3_double([sites_cart_residue[aa[1][0]]]) rev_i = fit_rotamers.rotamer_evaluator( sites_cart_start = sites_aa, unit_cell = self.unit_cell, two_mfo_dfc_map = self.target_map_data, mfo_dfc_map = self.residual_map_data) rev_first_atoms.append(rev_i) rev = fit_rotamers.rotamer_evaluator( sites_cart_start = sites_cart_residue, unit_cell = self.unit_cell, two_mfo_dfc_map = self.target_map_data, mfo_dfc_map = self.residual_map_data) residue_sites_best = sites_cart_residue.deep_copy() residue_sites_best, rotamer_id_best = \ fit_rotamers.torsion_search( residue_evaluator=rev, cluster_evaluators=rev_first_atoms, axes_and_atoms_to_rotate=eval_axes, rotamer_sites_cart=sites_cart_residue, rotamer_id_best=rotamer, residue_sites_best=residue_sites_best, params = self.torsion_params, rotamer_id = rotamer, include_ca_hinge = include_ca_hinge) sites_cart_moving.set_selected( residue_iselection, residue_sites_best) xray_structure.set_sites_cart(sites_cart_moving) cur_rotamer, cur_chis, cur_value = rotalyze.evaluate_rotamer( atom_group=atom_group, sidechain_angles=self.sa, rotamer_evaluator=self.rotamer_evaluator, rotamer_id=self.rotamer_id, all_dict=all_dict, sites_cart=sites_cart_moving) rotamer_match = (cur_rotamer == rotamer) if rev_start.is_better(sites_cart=residue_sites_best, percent_cutoff=0.15, verbose=True) and \ rotamer_match: sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [' N ', ' CA ', ' C ', ' O ', ' OXT', ' H ', ' HA ']: sidechain_only_iselection.append(i_seq) selection = flex.bool( len(sites_cart_moving), sidechain_only_iselection) selection_within = xray_structure.selection_within( radius = 1.0, selection = selection) #check for bad steric clashes created_clash = False for i, state in enumerate(selection_within): if state: if i not in sidechain_only_iselection: #print >> self.log, "atom clash: ", self.name_hash[i] created_clash = True if created_clash: sites_cart_moving.set_selected( residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [' N ', ' CA ', ' C ', ' O ']: sidechain_only_iselection.append(i_seq) sites_cart_sidechain = \ sites_cart_moving.select(sidechain_only_iselection) sites_frac_residue = self.unit_cell.fractionalize(sites_cart_sidechain) sigma_cutoff = 1.0 sigma_residue = [] for rsf in sites_frac_residue: if self.target_map_data.eight_point_interpolation(rsf) < sigma_cutoff: sigma_residue.append(False) else: sigma_residue.append(True) sigma_count = 0 for sigma_state in sigma_residue: if sigma_state: sigma_count += 1 else: break if sigma_count < sigma_count_start: sites_cart_moving.set_selected( residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False return True else: sites_cart_moving.set_selected( residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False
def shear_rotate(sites, i_seqs_primary1, i_seqs_primary2, i_seqs_middle, i_seqs_ca234, primary_axis1, primary_angle, secondary_axis1=None, secondary_axis2=None, secondary_axis3=None): """ Performs a "shear" move. First, rotates the atoms in sites indexed by i_seqs_primary1 within the Calpha 1-2-3 plane (around primary_axis1). Then, rotates the atoms in sites indexed by i_seqs_primary2 within the new Calpha 2'-3'-4 plane. Finally, moves the atoms in sites indexed by i_seqs_middle to plug the middle peptide into the Calpha 2'-3' gap. Directly modifies sites -- does not return anything. """ from scitbx.array_family import flex from scitbx import matrix from sys import float_info assert isinstance(primary_angle, float) assert (len(primary_axis1) == 2) if ((i_seqs_primary1 is None) or (i_seqs_primary2 is None) or (i_seqs_middle is None)): print "TODO set shear_rotate i_seqs automatically if not provided" return # prep for second primary rotation axis sites_start = sites.deep_copy() orig_dist = abs(matrix.col(sites_start[i_seqs_ca234[1]]) - \ matrix.col(sites_start[i_seqs_ca234[0]])) # this must be happening b/c previous shears didn't actually move atoms past # ca2 for some reason... assert (orig_dist > 3.7 and orig_dist < 3.9), \ "original ca2-ca3 distance for shear looks fishy: %.3f" % orig_dist # do first primary rotation sites_new = flex.vec3_double() for i_seq in i_seqs_primary1: xyz = matrix.rotate_point_around_axis(axis_point_1=primary_axis1[0], axis_point_2=primary_axis1[1], point=sites[i_seq], angle=primary_angle, deg=True) sites_new.append(xyz) sites.set_selected(i_seqs_primary1, sites_new) # prep for second primary rotation axis (cont'd) ca23 = matrix.col(sites[i_seqs_ca234[1]]) - matrix.col( sites[i_seqs_ca234[0]]) ca34 = matrix.col(sites[i_seqs_ca234[2]]) - matrix.col( sites[i_seqs_ca234[1]]) normal2 = ca23.cross(ca34) ca4_normal2 = matrix.col( sites_start[i_seqs_ca234[2]]) + matrix.col(normal2) primary_axis2 = [sites_start[i_seqs_ca234[2]], ca4_normal2] # do second primary rotation: # find magnitude that best preserves original ca2-ca3 distance best_diff_orig_dist = float_info.max best_sites_new = None best_theta = None theta = -1.5 * abs(primary_angle) theta_increment = 0.1 while (theta < 1.5 * abs(primary_angle)): ca3_new = matrix.rotate_point_around_axis( axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seqs_ca234[1]], angle=theta, deg=True) dist = abs(matrix.col(ca3_new) - matrix.col(sites[i_seqs_ca234[0]])) diff_orig_dist = abs(dist - orig_dist) if (diff_orig_dist < best_diff_orig_dist): best_theta = theta best_diff_orig_dist = diff_orig_dist # this rotation is best so far, # so do it to the *entire* third peptide and save the result sites_new = flex.vec3_double() for i_seq in i_seqs_primary2: xyz = matrix.rotate_point_around_axis( axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seq], angle=theta, deg=True) sites_new.append(xyz) best_sites_new = sites_new theta += theta_increment sites.set_selected(i_seqs_primary2, best_sites_new) final_dist = abs(matrix.col(sites[i_seqs_ca234[1]]) - \ matrix.col(sites[i_seqs_ca234[0]])) assert (abs(final_dist - orig_dist) < 0.1), "failed to close ca2-ca3 gap!" # plug in middle peptide by averaging the positions that result from # applying the two primary rotations to the middle peptide sites_new = flex.vec3_double() for i_seq in i_seqs_middle: xyz1 = matrix.rotate_point_around_axis(axis_point_1=primary_axis1[0], axis_point_2=primary_axis1[1], point=sites[i_seq], angle=primary_angle, deg=True) xyz2 = matrix.rotate_point_around_axis(axis_point_1=primary_axis2[0], axis_point_2=primary_axis2[1], point=sites[i_seq], angle=best_theta, deg=True) xyz_avg = (matrix.col(xyz1) + matrix.col(xyz2)) / 2 sites_new.append(xyz_avg) sites.set_selected(i_seqs_middle, sites_new)
def backrub_move( prev_res, cur_res, next_res, angle, move_oxygens=False, accept_worse_rama=False, rotamer_manager=None, rama_manager=None): import boost.python ext = boost.python.import_ext("mmtbx_validation_ramachandran_ext") from mmtbx_validation_ramachandran_ext import rama_eval from scitbx.matrix import rotate_point_around_axis from mmtbx.conformation_dependent_library.multi_residue_class import ThreeProteinResidues, \ RestraintsRegistry if abs(angle) < 1e-4: return if prev_res is None or next_res is None: return saved_res = [{},{},{}] for i, r in enumerate([prev_res, cur_res, next_res]): for a in r.atoms(): saved_res[i][a.name.strip()] = a.xyz if rotamer_manager is None: rotamer_manager = RotamerEval() prev_ca = prev_res.find_atom_by(name=" CA ") cur_ca = cur_res.find_atom_by(name=" CA ") next_ca = next_res.find_atom_by(name=" CA ") if prev_ca is None or next_ca is None or cur_ca is None: return atoms_to_move = [] atoms_to_move.append(prev_res.find_atom_by(name=" C ")) atoms_to_move.append(prev_res.find_atom_by(name=" O ")) for atom in cur_res.atoms(): atoms_to_move.append(atom) atoms_to_move.append(next_res.find_atom_by(name=" N ")) for atom in atoms_to_move: assert atom is not None new_xyz = rotate_point_around_axis( axis_point_1 = prev_ca.xyz, axis_point_2 = next_ca.xyz, point = atom.xyz, angle = angle, deg = True) atom.xyz = new_xyz if move_oxygens: registry = RestraintsRegistry() if rama_manager is None: rama_manager = rama_eval() tpr = ThreeProteinResidues(geometry=None, registry=registry) tpr.append(prev_res) tpr.append(cur_res) tpr.append(next_res) phi_psi_angles = tpr.get_phi_psi_angles() rama_key = tpr.get_ramalyze_key() ev_before = rama_manager.evaluate_angles(rama_key, phi_psi_angles[0], phi_psi_angles[1]) theta1 = _find_theta( ap1 = prev_ca.xyz, ap2 = cur_ca.xyz, cur_xyz = prev_res.find_atom_by(name=" O ").xyz, needed_xyz = saved_res[0]["O"]) theta2 = _find_theta( ap1 = cur_ca.xyz, ap2 = next_ca.xyz, cur_xyz = cur_res.find_atom_by(name=" O ").xyz, needed_xyz = saved_res[1]["O"]) for a in [prev_res.find_atom_by(name=" C "), prev_res.find_atom_by(name=" O "), cur_res.find_atom_by(name=" C ")]: new_xyz = rotate_point_around_axis( axis_point_1 = prev_ca.xyz, axis_point_2 = cur_ca.xyz, point = a.xyz, angle = theta1, deg = True) a.xyz = new_xyz for a in [cur_res.find_atom_by(name=" C "), cur_res.find_atom_by(name=" O "), next_res.find_atom_by(name=" N ")]: new_xyz = rotate_point_around_axis( axis_point_1 = cur_ca.xyz, axis_point_2 = next_ca.xyz, point = a.xyz, angle = theta2, deg = True) a.xyz = new_xyz phi_psi_angles = tpr.get_phi_psi_angles() rama_key = tpr.get_ramalyze_key() ev_after = rama_manager.evaluate_angles(rama_key, phi_psi_angles[0], phi_psi_angles[1]) if ev_before > ev_after and not accept_worse_rama: for a in [prev_res.find_atom_by(name=" C "), prev_res.find_atom_by(name=" O "), cur_res.find_atom_by(name=" C ")]: new_xyz = rotate_point_around_axis( axis_point_1 = prev_ca.xyz, axis_point_2 = cur_ca.xyz, point = a.xyz, angle = -theta1, deg = True) a.xyz = new_xyz for a in [cur_res.find_atom_by(name=" C "), cur_res.find_atom_by(name=" O "), next_res.find_atom_by(name=" N ")]: new_xyz = rotate_point_around_axis( axis_point_1 = cur_ca.xyz, axis_point_2 = next_ca.xyz, point = a.xyz, angle = -theta2, deg = True) a.xyz = new_xyz
def sample_angle ( i_seqs, sites_cart, map_coeffs, real_map, difference_map, sigma, angle_start, params, sampling_method="linear", unit_cell=None) : """ Given a set of four sites defining a rotatable dihedral angle, sample the density at the fourth site in small angular increments. returns: a tuple of lists containing the sampled density values (floats) for the primary map and optional difference map. """ frac_matrix = None if (unit_cell is None) : assert (map_coeffs is not None) unit_cell = map_coeffs.unit_cell() frac_matrix = unit_cell.fractionalization_matrix() assert (sampling_method != "direct") or (map_coeffs is not None) from cctbx import maptbx from scitbx.matrix import rotate_point_around_axis point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=sites_cart[3], angle=-angle_start, deg=True) # TODO: present option to have point (sites_cart[3]) be generated based on # idealized geometry. n_degrees = 0 densities = [] difference_densities = [] while (n_degrees < 360) : point = rotate_point_around_axis( axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=point, angle=params.sampling_angle, deg=True) point_frac = unit_cell.fractionalize(site_cart=point) rho = rho_fofc = None if (sampling_method == "spline") and (map_coeffs is not None) : rho = real_map.tricubic_interpolation(point_frac) if (difference_map is not None) : rho_fofc = difference_map.tricubic_interpolation(point_frac) elif (sampling_method == "linear") or (map_coeffs is None) : if (map_coeffs is None) : rho = maptbx.non_crystallographic_eight_point_interpolation( map=real_map, gridding_matrix=frac_matrix, site_cart=point) #allow_out_of_bounds=True) else : rho = real_map.eight_point_interpolation(point_frac) if (difference_map is not None) : rho_fofc = difference_map.eight_point_interpolation(point_frac) else : rho = map_coeffs.direct_summation_at_point( site_frac=point_frac, sigma=sigma).real densities.append(rho) if (rho_fofc is not None) : difference_densities.append(rho_fofc) n_degrees += params.sampling_angle #print densities return densities, difference_densities
def search(self, atom_group, all_dict, m_chis, r_chis, rotamer, sites_cart_moving, xray_structure, key): include_ca_hinge = False axis_and_atoms_to_rotate, tardy_labels= \ rotatable_bonds.axes_and_atoms_aa_specific( residue=atom_group, mon_lib_srv=self.mon_lib_srv, remove_clusters_with_all_h=True, include_labels=True, log=None) if (axis_and_atoms_to_rotate is None): print >> self.log, "Skipped %s rotamer (TARDY error)" % key return False assert len(m_chis) == len(r_chis) #exclude H-only clusters if necessary while len(axis_and_atoms_to_rotate) > len(m_chis): axis_and_atoms_to_rotate = \ axis_and_atoms_to_rotate[:-1] assert len(m_chis) == len(axis_and_atoms_to_rotate) counter = 0 residue_iselection = atom_group.atoms().extract_i_seq() cur_ca = None ca_add = None ca_axes = [] for atom in atom_group.atoms(): if atom.name == " CA ": cur_ca = atom.i_seq if cur_ca is not None: cur_c_alpha_hinges = self.c_alpha_hinges.get(cur_ca) if cur_c_alpha_hinges is not None: residue_length = len(tardy_labels) for ca_pt in cur_c_alpha_hinges[0]: residue_iselection.append(ca_pt) tardy_labels.append(self.name_hash[ca_pt][0:4]) for bb_pt in cur_c_alpha_hinges[1]: residue_iselection.append(bb_pt) tardy_labels.append(self.name_hash[bb_pt][0:4]) end_pts = (residue_length, residue_length + 1) group = [] for i, value in enumerate(tardy_labels): if i not in end_pts: group.append(i) ca_add = [end_pts, group] ca_axes.append(ca_add) for ax in axis_and_atoms_to_rotate: ca_axes.append(ax) sites_cart_residue = \ sites_cart_moving.select(residue_iselection) sites_cart_residue_start = sites_cart_residue.deep_copy() selection = flex.bool(len(sites_cart_moving), residue_iselection) rev_first_atoms = [] rev_start = rotamer_evaluator( sites_cart_start=sites_cart_residue_start, unit_cell=self.unit_cell, two_mfo_dfc_map=self.target_map_data, mfo_dfc_map=self.residual_map_data) sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [' N ', ' CA ', ' C ', ' O ']: sidechain_only_iselection.append(i_seq) sites_cart_sidechain = \ sites_cart_moving.select(sidechain_only_iselection) sites_frac_residue = self.unit_cell.fractionalize(sites_cart_sidechain) sigma_cutoff = 1.0 sigma_residue = [] for rsf in sites_frac_residue: if self.target_map_data.eight_point_interpolation( rsf) < sigma_cutoff: sigma_residue.append(False) else: sigma_residue.append(True) sigma_count_start = 0 for sigma_state in sigma_residue: if sigma_state: sigma_count_start += 1 else: break for aa in axis_and_atoms_to_rotate: axis = aa[0] atoms = aa[1] new_xyz = flex.vec3_double() angle_deg = r_chis[counter] - m_chis[counter] #skip angle rotations that are close to zero if math.fabs(angle_deg) < 0.01: counter += 1 continue if angle_deg < 0: angle_deg += 360.0 for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1=sites_cart_residue[axis[0]], axis_point_2=sites_cart_residue[axis[1]], point=sites_cart_residue[atom], angle=angle_deg, deg=True) sites_cart_residue[atom] = new_xyz counter += 1 #***** TEST ***** sites_cart_moving.set_selected(residue_iselection, sites_cart_residue) cur_rotamer, cur_chis, cur_value = rotalyze.evaluate_rotamer( atom_group=atom_group, sidechain_angles=self.sa, rotamer_evaluator=self.rotamer_evaluator, rotamer_id=self.rotamer_id, all_dict=all_dict, sites_cart=sites_cart_moving) assert rotamer == cur_rotamer #**************** if len(ca_axes) == 0: eval_axes = axis_and_atoms_to_rotate else: eval_axes = ca_axes include_ca_hinge = True for i_aa, aa in enumerate(eval_axes): if (i_aa == len(eval_axes) - 1): sites_aa = flex.vec3_double() for aa_ in aa[1]: sites_aa.append(sites_cart_residue[aa_]) elif i_aa == 0 and include_ca_hinge: sites_aa = flex.vec3_double() for aa_ in aa[1]: sites_aa.append(sites_cart_residue[aa_]) else: sites_aa = flex.vec3_double([sites_cart_residue[aa[1][0]]]) rev_i = rotamer_evaluator(sites_cart_start=sites_aa, unit_cell=self.unit_cell, two_mfo_dfc_map=self.target_map_data, mfo_dfc_map=self.residual_map_data) rev_first_atoms.append(rev_i) rev = rotamer_evaluator(sites_cart_start=sites_cart_residue, unit_cell=self.unit_cell, two_mfo_dfc_map=self.target_map_data, mfo_dfc_map=self.residual_map_data) residue_sites_best = sites_cart_residue.deep_copy() residue_sites_best, rotamer_id_best = \ torsion_search( residue_evaluator=rev, cluster_evaluators=rev_first_atoms, axes_and_atoms_to_rotate=eval_axes, rotamer_sites_cart=sites_cart_residue, rotamer_id_best=rotamer, residue_sites_best=residue_sites_best, params = self.torsion_params, rotamer_id = rotamer, include_ca_hinge = include_ca_hinge) sites_cart_moving.set_selected(residue_iselection, residue_sites_best) xray_structure.set_sites_cart(sites_cart_moving) cur_rotamer, cur_chis, cur_value = rotalyze.evaluate_rotamer( atom_group=atom_group, sidechain_angles=self.sa, rotamer_evaluator=self.rotamer_evaluator, rotamer_id=self.rotamer_id, all_dict=all_dict, sites_cart=sites_cart_moving) rotamer_match = (cur_rotamer == rotamer) if rev_start.is_better(sites_cart=residue_sites_best, percent_cutoff=0.15, verbose=True) and \ rotamer_match: sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [ ' N ', ' CA ', ' C ', ' O ', ' OXT', ' H ', ' HA ' ]: sidechain_only_iselection.append(i_seq) selection = flex.bool(len(sites_cart_moving), sidechain_only_iselection) selection_within = xray_structure.selection_within( radius=1.0, selection=selection) #check for bad steric clashes created_clash = False for i, state in enumerate(selection_within): if state: if i not in sidechain_only_iselection: #print >> self.log, "atom clash: ", self.name_hash[i] created_clash = True if created_clash: sites_cart_moving.set_selected(residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False sidechain_only_iselection = flex.size_t() for i_seq in residue_iselection: atom_name = self.name_hash[i_seq][0:4] if atom_name not in [' N ', ' CA ', ' C ', ' O ']: sidechain_only_iselection.append(i_seq) sites_cart_sidechain = \ sites_cart_moving.select(sidechain_only_iselection) sites_frac_residue = self.unit_cell.fractionalize( sites_cart_sidechain) sigma_cutoff = 1.0 sigma_residue = [] for rsf in sites_frac_residue: if self.target_map_data.eight_point_interpolation( rsf) < sigma_cutoff: sigma_residue.append(False) else: sigma_residue.append(True) sigma_count = 0 for sigma_state in sigma_residue: if sigma_state: sigma_count += 1 else: break if sigma_count < sigma_count_start: sites_cart_moving.set_selected(residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False return True else: sites_cart_moving.set_selected(residue_iselection, sites_cart_residue_start) xray_structure.set_sites_cart(sites_cart_moving) return False
def torsion_search(residue_evaluator, cluster_evaluators, axes_and_atoms_to_rotate, rotamer_sites_cart, rotamer_id_best, residue_sites_best, params=None, rotamer_id=None, include_ca_hinge=False): if (params is None): params = torsion_search_params().extract().torsion_search params.range_start = 0 params.range_stop = 360 params.step = 1.0 rotamer_sites_cart_ = rotamer_sites_cart.deep_copy() n_clusters = len(axes_and_atoms_to_rotate) c_counter = 0 for cluster_evaluator, aa in zip(cluster_evaluators, axes_and_atoms_to_rotate): #account for CA hinge at beginning of search if include_ca_hinge and c_counter == 0: cur_range_start = -6.0 cur_range_stop = 6.0 else: cur_range_start = params.range_start cur_range_stop = params.range_stop c_counter += 1 axis = aa[0] atoms = aa[1] angle_deg_best = None angle_deg_good = None for angle_deg in generate_range(start=cur_range_start, stop=cur_range_stop, step=params.step): if (c_counter != n_clusters): if include_ca_hinge and c_counter == 1: new_xyz = flex.vec3_double() for atom in atoms: new_xyz.append( rotate_point_around_axis( axis_point_1=rotamer_sites_cart[axis[0]], axis_point_2=rotamer_sites_cart[axis[1]], point=rotamer_sites_cart[atom], angle=angle_deg, deg=True)) else: point_local = rotamer_sites_cart[atoms[0]] new_xyz = flex.vec3_double([ rotate_point_around_axis( axis_point_1=rotamer_sites_cart[axis[0]], axis_point_2=rotamer_sites_cart[axis[1]], point=point_local, angle=angle_deg, deg=True) ]) else: new_xyz = flex.vec3_double() for atom in atoms: new_xyz.append( rotate_point_around_axis( axis_point_1=rotamer_sites_cart[axis[0]], axis_point_2=rotamer_sites_cart[axis[1]], point=rotamer_sites_cart[atom], angle=angle_deg, deg=True)) if (cluster_evaluator.is_better(sites_cart=new_xyz)): if (angle_deg_best is not None and abs(abs(angle_deg_best) - abs(angle_deg)) > params.min_angle_between_solutions): angle_deg_good = angle_deg_best angle_deg_best = angle_deg if (angle_deg_best is not None): for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1=rotamer_sites_cart[axis[0]], axis_point_2=rotamer_sites_cart[axis[1]], point=rotamer_sites_cart[atom], angle=angle_deg_best, deg=True) rotamer_sites_cart[atom] = new_xyz if (angle_deg_good is not None): for atom in atoms: new_xyz = rotate_point_around_axis( axis_point_1=rotamer_sites_cart_[axis[0]], axis_point_2=rotamer_sites_cart_[axis[1]], point=rotamer_sites_cart_[atom], angle=angle_deg_best, deg=True) rotamer_sites_cart_[atom] = new_xyz for rsc in [rotamer_sites_cart, rotamer_sites_cart_]: if (residue_evaluator.is_better(sites_cart=rsc)): rotamer_id_best = rotamer_id residue_sites_best = rsc.deep_copy() return residue_sites_best, rotamer_id_best
def sample_angle(i_seqs, sites_cart, map_coeffs, real_map, difference_map, sigma, angle_start, params, sampling_method="linear", unit_cell=None): """ Given a set of four sites defining a rotatable dihedral angle, sample the density at the fourth site in small angular increments. returns: a tuple of lists containing the sampled density values (floats) for the primary map and optional difference map. """ frac_matrix = None if (unit_cell is None): assert (map_coeffs is not None) unit_cell = map_coeffs.unit_cell() frac_matrix = unit_cell.fractionalization_matrix() assert (sampling_method != "direct") or (map_coeffs is not None) from cctbx import maptbx from scitbx.matrix import rotate_point_around_axis point = rotate_point_around_axis(axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=sites_cart[3], angle=-angle_start, deg=True) # TODO: present option to have point (sites_cart[3]) be generated based on # idealized geometry. n_degrees = 0 densities = [] difference_densities = [] while (n_degrees < 360): point = rotate_point_around_axis(axis_point_1=sites_cart[1], axis_point_2=sites_cart[2], point=point, angle=params.sampling_angle, deg=True) point_frac = unit_cell.fractionalize(site_cart=point) rho = rho_fofc = None if (sampling_method == "spline") and (map_coeffs is not None): rho = real_map.tricubic_interpolation(point_frac) if (difference_map is not None): rho_fofc = difference_map.tricubic_interpolation(point_frac) elif (sampling_method == "linear") or (map_coeffs is None): if (map_coeffs is None): rho = maptbx.non_crystallographic_eight_point_interpolation( map=real_map, gridding_matrix=frac_matrix, site_cart=point) #allow_out_of_bounds=True) else: rho = real_map.eight_point_interpolation(point_frac) if (difference_map is not None): rho_fofc = difference_map.eight_point_interpolation( point_frac) else: rho = map_coeffs.direct_summation_at_point(site_frac=point_frac, sigma=sigma).real densities.append(rho) if (rho_fofc is not None): difference_densities.append(rho_fofc) n_degrees += params.sampling_angle #print densities return densities, difference_densities