Esempio n. 1
0
def filter_before_build (
    pdb_hierarchy,
    fmodel,
    geometry_restraints_manager,
    selection=None,
    params=None,
    verbose=True,
    log=sys.stdout) :
  """
  Pick residues suitable for building alternate conformations - by default,
  this means no MolProbity/geometry outliers, good fit to map, no missing
  atoms, and no pre-existing alternates, but with significant difference
  density nearby.
  """
  from mmtbx.validation import molprobity
  from mmtbx.rotamer import rotamer_eval
  import mmtbx.monomer_library.server
  from mmtbx import building
  from iotbx.pdb import common_residue_names_get_class
  from scitbx.array_family import flex
  if (selection is None) :
    selection = flex.bool(fmodel.xray_structure.scatterers().size(), True)
  pdb_atoms = pdb_hierarchy.atoms()
  assert (pdb_atoms.size() == fmodel.xray_structure.scatterers().size())
  pdb_atoms.reset_i_seq()
  full_validation = molprobity.molprobity(
    pdb_hierarchy=pdb_hierarchy,
    fmodel=fmodel,
    geometry_restraints_manager=geometry_restraints_manager,
    outliers_only=False,
    rotamer_library="8000")
  if (verbose) :
    full_validation.show(out=log)
  multi_criterion = full_validation.as_multi_criterion_view()
  if (params is None) :
    params = libtbx.phil.parse(filter_params_str).extract()
  mon_lib_srv = mmtbx.monomer_library.server.server()
  two_fofc_map, fofc_map = building.get_difference_maps(fmodel=fmodel)
  residues = []
  filters = params.discard_outliers
  make_sub_header("Identifying candidates for building", out=log)
  # TODO parallelize
  for chain in pdb_hierarchy.only_model().chains() :
    if (not chain.is_protein()) :
      continue
    for residue_group in chain.residue_groups() :
      atom_groups = residue_group.atom_groups()
      id_str = residue_group.id_str()
      i_seqs = residue_group.atoms().extract_i_seq()
      residue_sel = selection.select(i_seqs)
      if (not residue_sel.all_eq(True)) :
        continue
      if (len(atom_groups) > 1) :
        print >> log, "  %s is already multi-conformer" % id_str
        continue
      atom_group = atom_groups[0]
      res_class = common_residue_names_get_class(atom_group.resname)
      if (res_class != "common_amino_acid") :
        print >> log, "  %s: non-standard residue" % id_str
        continue
      missing_atoms = rotamer_eval.eval_residue_completeness(
        residue=atom_group,
        mon_lib_srv=mon_lib_srv,
        ignore_hydrogens=True)
      if (len(missing_atoms) > 0) :
        # residues modeled as pseudo-ALA are allowed by default; partially
        # missing sidechains are more problematic
        if ((building.is_stub_residue(atom_group)) and
            (not params.ignore_stub_residues)) :
          pass
        else :
          print >> log, "  %s: missing or incomplete sidechain" % \
            (id_str, len(missing_atoms))
          continue
      validation = multi_criterion.get_residue_group_data(residue_group)
      is_outlier = is_validation_outlier(validation, params)
      if (is_outlier) :
        print >> log, "  %s" % str(validation)
        continue
      if (params.use_difference_map) :
        i_seqs_no_hd = building.get_non_hydrogen_atom_indices(residue_group)
        map_stats = building.local_density_quality(
          fofc_map=fofc_map,
          two_fofc_map=two_fofc_map,
          atom_selection=i_seqs_no_hd,
          xray_structure=fmodel.xray_structure,
          radius=params.sampling_radius)
        if ((map_stats.number_of_atoms_below_fofc_map_level() == 0) and
            (map_stats.fraction_of_nearby_grid_points_above_cutoff()==0)) :
          if (verbose) :
            print >> log, "  no difference density for %s" % id_str
          continue
      residues.append(residue_group.only_atom_group())
  if (len(residues) == 0) :
    raise Sorry("No residues passed the filtering criteria.")
  print >> log, ""
  print >> log, "Alternate conformations will be tried for %d residue(s):" % \
      len(residues)
  building.show_chain_resseq_ranges(residues, out=log, prefix="  ")
  print >> log, ""
  return residues
Esempio n. 2
0
 def __call__(self,
              atom_group,
              log,
              window_size=2,
              backbone_sample_angle=10,
              anneal=False,
              annealing_temperature=1000,
              use_chi1_sampling=False):
     import iotbx.pdb.hierarchy
     from scitbx.array_family import flex
     assert (atom_group is not None)
     pdb_hierarchy = self.pdb_hierarchy.deep_copy()
     xray_structure = self.xray_structure.deep_copy_scatterers()
     geometry_restraints_manager = self.geometry_restraints_manager
     # FIXME this doesn't work - can't recover the atom_group afterwards!
     #hd_sel = xray_structure.hd_selection()
     #n_hydrogen = hd_sel.count(True)
     #if (n_hydrogen > 0):
     #  non_hd_sel = ~hd_sel
     #  pdb_hierarchy = pdb_hierarchy.select(non_hd_sel)
     #  xray_structure = xray_structure.select(non_hd_sel)
     #  geometry_restraints_manager = geometry_restraints_manager.select(
     #    non_hd_sel)
     pdb_atoms = pdb_hierarchy.atoms()
     pdb_atoms.reset_i_seq()
     isel = building.extract_iselection([atom_group])
     atom_group = pdb_atoms[isel[0]].parent()
     atom_group_start = atom_group.detached_copy()
     needs_rebuild = not building.is_stub_residue(atom_group)
     residue_group = atom_group.parent()
     assert (len(residue_group.atom_groups()) == 1)
     sel_residues = building.get_window_around_residue(
         residue=atom_group, window_size=window_size)
     # get rid of sidechains for surrounding residues only
     adjacent_residues = []
     for other_rg in sel_residues:
         if (other_rg != residue_group):
             adjacent_residues.append(other_rg)
     building.remove_sidechain_atoms(adjacent_residues)
     pdb_atoms = pdb_hierarchy.atoms()
     adjacent_trimmed_atom_names = pdb_atoms.extract_name()
     adjacent_trimmed_sel = pdb_atoms.extract_i_seq()
     xrs_adjacent_trimmed = xray_structure.select(adjacent_trimmed_sel)
     grm_adjacent_trimmed = geometry_restraints_manager.select(
         adjacent_trimmed_sel)
     pdb_atoms.reset_i_seq()
     # get rid of central sidechain and refine mainchain for entire window
     truncate = (not atom_group.resname in ["GLY", "ALA"])  # XXX PRO?
     if (truncate):
         building.remove_sidechain_atoms([atom_group])
     pdb_atoms = pdb_hierarchy.atoms()
     all_mc_sel = pdb_atoms.extract_i_seq()
     xrs_mc = xrs_adjacent_trimmed.select(all_mc_sel)
     pdb_atoms.reset_i_seq()
     window_mc_sel = building.extract_iselection(sel_residues)
     selection = flex.bool(pdb_atoms.size(),
                           False).set_selected(window_mc_sel, True)
     restraints_manager = grm_adjacent_trimmed.select(all_mc_sel)
     box = building.box_build_refine_base(
         xray_structure=xrs_mc,
         pdb_hierarchy=pdb_hierarchy,
         selection=selection,
         processed_pdb_file=None,
         target_map=self.target_map,
         geometry_restraints_manager=restraints_manager.geometry,
         d_min=self.d_min,
         out=null_out(),
         debug=True)
     box.restrain_atoms(selection=box.others_in_box, reference_sigma=0.1)
     box.real_space_refine(selection=box.selection_in_box)
     sites_new = box.update_original_coordinates()
     pdb_atoms.set_xyz(sites_new)
     # extend and replace existing residue.  this is done in such a way that
     # the original atom ordering for the central residue is preserved, which
     # allows us to use the pre-existing geometry restraints instead of
     # re-calculating them every time this function is called.
     target_atom_group = self.ideal_dict[atom_group.resname.lower()].\
       only_model().only_chain().only_residue_group().only_atom_group()
     new_atom_group_base = extend_sidechains.extend_residue(
         residue=atom_group,
         target_atom_group=target_atom_group,
         mon_lib_srv=self.mon_lib_srv)
     new_atom_group = iotbx.pdb.hierarchy.atom_group(
         resname=atom_group.resname)
     for atom in atom_group_start.atoms():
         for new_atom in new_atom_group_base.atoms():
             if (new_atom.name == atom.name):
                 new_atom_group.append_atom(new_atom.detached_copy())
     n_atoms_new = len(new_atom_group.atoms())
     n_atoms_start = len(atom_group_start.atoms())
     if (n_atoms_new != n_atoms_start):
         raise RuntimeError(
             ("Inconsistent atom counts for residue %s after " +
              "building (%d versus %d).") %
             (atom_group.id_str(), n_atoms_start, n_atoms_new))
     rg = atom_group.parent()
     rg.remove_atom_group(atom_group)
     rg.append_atom_group(new_atom_group)
     pdb_atoms = pdb_hierarchy.atoms()
     pdb_atoms.reset_i_seq()
     new_names = pdb_atoms.extract_name()
     assert new_names.all_eq(adjacent_trimmed_atom_names)
     # get new box around this residue
     residue_sel = building.extract_iselection([new_atom_group])
     selection = flex.bool(pdb_atoms.size(),
                           False).set_selected(residue_sel, True)
     xrs_adjacent_trimmed.set_sites_cart(pdb_atoms.extract_xyz())
     box = building.box_build_refine_base(
         xray_structure=xrs_adjacent_trimmed,
         pdb_hierarchy=pdb_hierarchy,
         selection=selection,
         processed_pdb_file=None,
         target_map=self.target_map,
         geometry_restraints_manager=grm_adjacent_trimmed.geometry,
         d_min=self.d_min,
         out=null_out(),
         debug=True)
     # place sidechain using mmtbx.refinement.real_space.fit_residue
     if ((atom_group.resname in rotatable_sidechain_atoms)
             and (use_chi1_sampling)):
         fit_chi1_simple(residue=box.only_residue(),
                         unit_cell=box.unit_cell_box,
                         target_map=box.target_map_box,
                         rotamer_eval=self.rotamer_eval)
         box.update_sites_from_pdb_atoms()
     else:
         box.fit_residue_in_box(backbone_sample_angle=backbone_sample_angle)
     if (anneal):
         box.anneal(start_temperature=annealing_temperature)
     #box.real_space_refine()
     sites_new = box.update_original_coordinates()
     pdb_hierarchy.atoms().set_xyz(sites_new)
     return building.atom_group_as_hierarchy(new_atom_group)
Esempio n. 3
0
 def __call__ (self,
     atom_group,
     log,
     window_size=2,
     backbone_sample_angle=10,
     anneal=False,
     annealing_temperature=1000,
     use_chi1_sampling=False) :
   import iotbx.pdb.hierarchy
   from scitbx.array_family import flex
   assert (atom_group is not None)
   pdb_hierarchy = self.pdb_hierarchy.deep_copy()
   xray_structure = self.xray_structure.deep_copy_scatterers()
   geometry_restraints_manager = self.geometry_restraints_manager
   # FIXME this doesn't work - can't recover the atom_group afterwards!
   #hd_sel = xray_structure.hd_selection()
   #n_hydrogen = hd_sel.count(True)
   #if (n_hydrogen > 0) :
   #  non_hd_sel = ~hd_sel
   #  pdb_hierarchy = pdb_hierarchy.select(non_hd_sel)
   #  xray_structure = xray_structure.select(non_hd_sel)
   #  geometry_restraints_manager = geometry_restraints_manager.select(
   #    non_hd_sel)
   pdb_atoms = pdb_hierarchy.atoms()
   pdb_atoms.reset_i_seq()
   isel = building.extract_iselection([atom_group])
   atom_group = pdb_atoms[isel[0]].parent()
   atom_group_start = atom_group.detached_copy()
   needs_rebuild = not building.is_stub_residue(atom_group)
   residue_group = atom_group.parent()
   assert (len(residue_group.atom_groups()) == 1)
   sel_residues = building.get_window_around_residue(
     residue=atom_group,
     window_size=window_size)
   # get rid of sidechains for surrounding residues only
   adjacent_residues = []
   for other_rg in sel_residues :
     if (other_rg != residue_group) :
       adjacent_residues.append(other_rg)
   building.remove_sidechain_atoms(adjacent_residues)
   pdb_atoms = pdb_hierarchy.atoms()
   adjacent_trimmed_atom_names = pdb_atoms.extract_name()
   adjacent_trimmed_sel = pdb_atoms.extract_i_seq()
   xrs_adjacent_trimmed = xray_structure.select(adjacent_trimmed_sel)
   grm_adjacent_trimmed = geometry_restraints_manager.select(
     adjacent_trimmed_sel)
   pdb_atoms.reset_i_seq()
   # get rid of central sidechain and refine mainchain for entire window
   truncate = (not atom_group.resname in ["GLY","ALA"]) # XXX PRO?
   if (truncate) :
     building.remove_sidechain_atoms([ atom_group ])
   pdb_atoms = pdb_hierarchy.atoms()
   all_mc_sel = pdb_atoms.extract_i_seq()
   xrs_mc = xrs_adjacent_trimmed.select(all_mc_sel)
   pdb_atoms.reset_i_seq()
   window_mc_sel = building.extract_iselection(sel_residues)
   selection = flex.bool(pdb_atoms.size(), False).set_selected(window_mc_sel,
     True)
   restraints_manager = grm_adjacent_trimmed.select(all_mc_sel)
   box = building.box_build_refine_base(
     xray_structure=xrs_mc,
     pdb_hierarchy=pdb_hierarchy,
     selection=selection,
     processed_pdb_file=None,
     target_map=self.target_map,
     geometry_restraints_manager=restraints_manager.geometry,
     d_min=self.d_min,
     out=null_out(),
     debug=True)
   box.restrain_atoms(
     selection=box.others_in_box,
     reference_sigma=0.1)
   box.real_space_refine(selection=box.selection_in_box)
   sites_new = box.update_original_coordinates()
   pdb_atoms.set_xyz(sites_new)
   # extend and replace existing residue.  this is done in such a way that
   # the original atom ordering for the central residue is preserved, which
   # allows us to use the pre-existing geometry restraints instead of
   # re-calculating them every time this function is called.
   new_atom_group_base = extend_sidechains.extend_residue(
     residue=atom_group,
     ideal_dict=self.ideal_dict,
     hydrogens=False,
     mon_lib_srv=self.mon_lib_srv,
     match_conformation=True)
   new_atom_group = iotbx.pdb.hierarchy.atom_group(resname=atom_group.resname)
   for atom in atom_group_start.atoms() :
     for new_atom in new_atom_group_base.atoms() :
       if (new_atom.name == atom.name) :
         new_atom_group.append_atom(new_atom.detached_copy())
   n_atoms_new = len(new_atom_group.atoms())
   n_atoms_start = len(atom_group_start.atoms())
   if (n_atoms_new != n_atoms_start) :
     raise RuntimeError(("Inconsistent atom counts for residue %s after "+
       "building (%d versus %d).") % (atom_group.id_str(), n_atoms_start,
       n_atoms_new))
   rg = atom_group.parent()
   rg.remove_atom_group(atom_group)
   rg.append_atom_group(new_atom_group)
   pdb_atoms = pdb_hierarchy.atoms()
   pdb_atoms.reset_i_seq()
   new_names = pdb_atoms.extract_name()
   assert new_names.all_eq(adjacent_trimmed_atom_names)
   # get new box around this residue
   residue_sel = building.extract_iselection([ new_atom_group ])
   selection = flex.bool(pdb_atoms.size(), False).set_selected(residue_sel,
     True)
   xrs_adjacent_trimmed.set_sites_cart(pdb_atoms.extract_xyz())
   box = building.box_build_refine_base(
     xray_structure=xrs_adjacent_trimmed,
     pdb_hierarchy=pdb_hierarchy,
     selection=selection,
     processed_pdb_file=None,
     target_map=self.target_map,
     geometry_restraints_manager=grm_adjacent_trimmed.geometry,
     d_min=self.d_min,
     out=null_out(),
     debug=True)
   # place sidechain using mmtbx.refinement.real_space.fit_residue
   if ((atom_group.resname in rotatable_sidechain_atoms) and
       (use_chi1_sampling)) :
     fit_chi1_simple(
       residue=box.only_residue(),
       unit_cell=box.unit_cell_box,
       target_map=box.target_map_box,
       rotamer_eval=self.rotamer_eval)
     box.update_sites_from_pdb_atoms()
   else :
     box.fit_residue_in_box(backbone_sample_angle=backbone_sample_angle)
   if (anneal) :
     box.anneal(start_temperature=annealing_temperature)
   #box.real_space_refine()
   sites_new = box.update_original_coordinates()
   pdb_hierarchy.atoms().set_xyz(sites_new)
   return building.atom_group_as_hierarchy(new_atom_group)