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 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 residue_iteration( pdb_hierarchy, xray_structure, selection, alpha_selection, target_map_data, model_map_data, residual_map_data, rsr_manager, params, validator, log, ): assert target_map_data.focus() == model_map_data.focus() assert target_map_data.all() == model_map_data.all() from mmtbx.secondary_structure import proteins import mmtbx.rotamer import iotbx.pdb from scitbx.array_family import flex alpha_isel = alpha_selection.iselection() fmt1 = " |--------START--------| |--------FINAL--------|" fmt2 = " residue map_cc 2mFo-DFc mFo-DFc map_cc 2mFo-DFc mFo-DFc " "rotation" fmt3 = " %12s%7.4f %8.2f %7.2f %6.4f %7.2f %7.2f %4.1fdeg" print >> log, fmt1 print >> log, fmt2 unit_cell = xray_structure.unit_cell() map_selector = select_map( unit_cell=xray_structure.unit_cell(), target_map_data=target_map_data, model_map_data=model_map_data ) minimize = regularizer(rsr_manager.geometry_restraints_manager) get_class = iotbx.pdb.common_residue_names_get_class n_other_residues = 0 n_amino_acids_ignored = 0 n_amino_acids_scored = 0 sites_cart_start = xray_structure.sites_cart() atoms = pdb_hierarchy.atoms() atom_names = atoms.extract_name() result = [] for model in pdb_hierarchy.models(): for chain in model.chains(): for conformer in chain.conformers(): residues = conformer.residues() for i_res in range(len(residues) - 1): residue0 = None if i_res > 0: residue0 = residues[i_res - 1] residue1 = residues[i_res] residue2 = residues[i_res + 1] resseq1 = residue1.resseq_as_int() resseq2 = residue2.resseq_as_int() # XXX this is gross, but we can't assume sequential residue # numbering - a duplicate resseq is allowed if the insertion code # is non-blank. if not ( (resseq2 == (resseq1 + 1)) or ((resseq2 == resseq1) and (residue1.icode != residue2.icode)) ): continue if get_class(residue1.resname) == "common_amino_acid": residue_id_str = residue1.id_str(suppress_segid=1)[-12:] residue1_iselection = residue1.atoms().extract_i_seq() residue2_iselection = residue2.atoms().extract_i_seq() (ca1, ca2) = extract_calpha_atoms( residue1_isel=residue1_iselection, residue2_isel=residue2_iselection, atom_names=atom_names ) if None in [ca1, ca2]: continue # missing flanking C-alphas peptide_isel = extract_peptide_atoms( residue1_isel=residue1_iselection, residue2_isel=residue2_iselection, atom_names=atom_names ) if peptide_isel is None: continue # don't waste time on incomplete peptides # pre-validation against Ramachandran plot rama_res_type = "general" if residue1.resname in ["ILE", "VAL"]: rama_res_type = "isoleucine or valine" elif residue1.resname == "PRO": continue # FIXME elif residue1.resname == "GLY": rama_res_type = "glycine" elif residue2.resname == "PRO": rama_res_type = "pre-proline" phi_psi_i_seqs = [None] * 5 (phi, psi) = (None, None) if residue0 is not None: resseq0 = residue0.resseq_as_int() if (resseq0 == (resseq1 - 1)) or ( (resseq0 == resseq1) and (residue0.icode != residue1.icode) ): phi_psi_i_seqs = mmtbx.rotamer.get_phi_psi_indices( prev_res=residue0, residue=residue1, next_res=residue2 ) if not None in phi_psi_i_seqs: (phi, psi) = mmtbx.rotamer.phi_psi_from_sites( i_seqs=phi_psi_i_seqs, sites_cart=sites_cart_start ) bad_phi_psi = False # not necessarily an outlier # check for helical conformation (in which case we skip this), # or for disallowed region of Ramachandran plot if (phi is not None) and (psi is not None): common_i_seqs = alpha_isel.intersection(residue1_iselection) if common_i_seqs.size() != 0: if proteins.is_approximately_helical(phi, psi): continue # helical, don't flip! elif (-160 < phi < -20) and (psi > 60): bad_phi_psi = True # not helical, try flipping else: pass # TODO something smart, hopefully... else: bad_phi_psi = validator.eval_phi_psi(rama_res_type, phi, psi) residues_iselection = flex.size_t() residues_iselection.extend(residue1_iselection) residues_iselection.extend(residue2_iselection) if (bad_phi_psi) or ( map_selector.is_refinement_needed( peptide_isel=peptide_isel, sites_cart=sites_cart_start, atoms=atoms, cc_limit=params.poor_cc_threshold, ) ): sites_cart_peptide = sites_cart_start.select(peptide_isel) rsel, rs = fit_rotamers.include_residue_selection( selection=selection, residue_iselection=residues_iselection ) rev = fit_rotamers.rotamer_evaluator( sites_cart_start=sites_cart_peptide, unit_cell=unit_cell, two_mfo_dfc_map=target_map_data, mfo_dfc_map=residual_map_data, ) cc_start = map_selector.get_cc( sites_cart=sites_cart_peptide, residue_iselection=residues_iselection ) rm = fit_rotamers.residue_rsr_monitor( residue_id_str=residue_id_str, selection=peptide_isel.deep_copy(), sites_cart=sites_cart_peptide.deep_copy(), twomfodfc=rev.t1_start, mfodfc=rev.t2_start, cc=cc_start, residue_type=rama_res_type, validate_iselection=phi_psi_i_seqs, ) if params.torsion_grid_search: torsion_params = params.torsion_search else: torsion_params = torsion_search_params().extract() torsion_params.start = 0 torsion_params.stop = 0 sites_cart_best, angle_best = rotation_search( residue_evaluator=rev, ca1=ca1, ca2=ca2, sites_cart=sites_cart_start, peptide_isel=peptide_isel, # carbonyl_isel=carbonyl_isel, params=params.torsion_search, ) if angle_best is None: continue cc_flipped = map_selector.get_cc( sites_cart=sites_cart_best, residue_iselection=residues_iselection ) cc_end = None if not params.real_space_refine_peptide: sites_cart_start = sites_cart_start.set_selected(peptide_isel, sites_cart_best) cc_end = cc_flipped else: tmp = sites_cart_start.set_selected(peptide_isel, sites_cart_best) sites_cart_refined = rsr_manager.refine_restrained(tmp.select(rsel), rsel, rs) if rev.is_better(sites_cart_refined): sites_cart_start = sites_cart_start.set_selected(peptide_isel, sites_cart_best) cc_end = map_selector.get_cc( sites_cart=sites_cart_refined, residue_iselection=residues_iselection ) else: # undo changes sites_cart_start = sites_cart_start.set_selected(peptide_isel, sites_cart_peptide) if cc_end is not None: result.append(rm) print >> log, fmt3 % ( residue_id_str, cc_start, rev.t1_start, rev.t2_start, cc_end, rev.t1_best, rev.t2_best, angle_best, ) xray_structure.set_sites_cart(sites_cart_start) return result