Ejemplo n.º 1
0
def exercise_map_utils () :
  #
  # UNSTABLE
  #
  hierarchy, fmodel = get_1yjp_pdb_and_fmodel()
  sel_cache = hierarchy.atom_selection_cache()
  sele = sel_cache.selection("resseq 5 and (name CD or name OE1 or name NE2)")
  sele_all = sel_cache.selection("resseq 5")
  fmodel.xray_structure.scale_adp(factor=0.5, selection=sele)
  fmodel.update_xray_structure(update_f_calc=True)
  two_fofc_map, fofc_map = building.get_difference_maps(fmodel)
  map_stats = building.local_density_quality(
    fofc_map=fofc_map,
    two_fofc_map=two_fofc_map,
    atom_selection=sele_all,
    xray_structure=fmodel.xray_structure)
  out = StringIO()
  map_stats.show_atoms_outside_density(out=out, two_fofc_cutoff=3.0)
  pdb_strs = [ l.split(":")[0] for l in out.getvalue().splitlines() ]
  assert len(pdb_strs) > 0
  # XXX there seems to be a stochastic effect here
  #assert (pdb_strs == ['pdb=" CA  GLN A   5 "', 'pdb=" CB  GLN A   5 "',
  #                     'pdb=" CD  GLN A   5 "', 'pdb=" NE2 GLN A   5 "']), \
  #  pdb_strs
  fc_map = fmodel.map_coefficients(map_type="Fc").fft_map(
    resolution_factor=0.25).apply_sigma_scaling().real_map_unpadded()
  assert (map_stats.number_of_atoms_below_fofc_map_level() == 3)
  assert (map_stats.fraction_of_nearby_grid_points_above_cutoff() > 0.0)
  stats = building.get_model_map_stats(
    selection=sele_all,
    target_map=two_fofc_map,
    model_map=fc_map,
    unit_cell=fmodel.xray_structure.unit_cell(),
    sites_cart=fmodel.xray_structure.sites_cart(),
    pdb_atoms=hierarchy.atoms())
Ejemplo n.º 2
0
def exercise_map_utils () :
  #
  # UNSTABLE 2x
  #
  hierarchy, fmodel = get_1yjp_pdb_and_fmodel()
  sel_cache = hierarchy.atom_selection_cache()
  sele = sel_cache.selection("resseq 5 and (name CD or name OE1 or name NE2)")
  sele_all = sel_cache.selection("resseq 5")
  fmodel.xray_structure.scale_adp(factor=0.5, selection=sele)
  fmodel.update_xray_structure(update_f_calc=True)
  two_fofc_map, fofc_map = building.get_difference_maps(fmodel)
  map_stats = building.local_density_quality(
    fofc_map=fofc_map,
    two_fofc_map=two_fofc_map,
    atom_selection=sele_all,
    xray_structure=fmodel.xray_structure)
  out = StringIO()
  map_stats.show_atoms_outside_density(out=out, two_fofc_cutoff=3.0)
  pdb_strs = [ l.split(":")[0] for l in out.getvalue().splitlines() ]
  assert len(pdb_strs) > 0
  # XXX there seems to be a stochastic effect here
  #assert (pdb_strs == ['pdb=" CA  GLN A   5 "', 'pdb=" CB  GLN A   5 "',
  #                     'pdb=" CD  GLN A   5 "', 'pdb=" NE2 GLN A   5 "']), \
  #  pdb_strs
  fc_map = fmodel.map_coefficients(map_type="Fc").fft_map(
    resolution_factor=0.25).apply_sigma_scaling().real_map_unpadded()
  assert (map_stats.number_of_atoms_below_fofc_map_level() == 3)
  assert (map_stats.fraction_of_nearby_grid_points_above_cutoff() > 0.0)
  stats = building.get_model_map_stats(
    selection=sele_all,
    target_map=two_fofc_map,
    model_map=fc_map,
    unit_cell=fmodel.xray_structure.unit_cell(),
    sites_cart=fmodel.xray_structure.sites_cart(),
    pdb_atoms=hierarchy.atoms())
Ejemplo n.º 3
0
def process_results(pdb_hierarchy,
                    fmodel,
                    residues_in,
                    building_trials,
                    params,
                    verbose=False,
                    log=sys.stdout):
    assert (len(residues_in) == len(building_trials))
    from mmtbx.rotamer import rotamer_eval
    n_alternates = 0
    unit_cell = fmodel.xray_structure.unit_cell()
    two_fofc_map, fofc_map = building.get_difference_maps(fmodel)
    rot_eval = rotamer_eval.RotamerEval(data_version="8000")
    for main_conf, trials in zip(residues_in, building_trials):
        if (trials is None):
            print("WARNING: error building %s" % main_conf.id_str(), file=log)
            continue
        if (len(trials) == 0):
            continue
        res_log = StringIO()
        print("  %s:" % main_conf.id_str(), file=res_log)
        main_rotamer = alt_rotamer = None
        if (not main_conf.resname in ["GLY", "PRO", "ALA"]):
            main_rotamer = rot_eval.evaluate_residue(main_conf)
            assert (main_rotamer != "OUTLIER")
        best_trial = pick_best_alternate(trials=trials,
                                         params=params,
                                         rotamer=main_rotamer,
                                         log=res_log)
        if (best_trial is None):
            continue
        new_conf = best_trial.as_atom_group()
        changed_rotamer = (best_trial.rotamer != main_rotamer)
        skip = False
        flag = ""
        stats = best_trial.stats
        # FIXME this needs to be made more consistent with the filtering criteria
        # in disorder/__init__.py
        if ((stats.rmsd < params.rmsd_min)
                and (stats.max_dev < params.rmsd_min)
                and (not changed_rotamer)):
            skip = True
        print("    selected conformer (occ=%.2f):" % \
          best_trial.occupancy, file=res_log)
        res_log2 = StringIO()
        density_quality = building.residue_density_quality(
            atom_group=new_conf,
            unit_cell=unit_cell,
            two_fofc_map=two_fofc_map,
            fofc_map=fofc_map)
        if (main_conf.resname in ["CYS", "MET", "MSE"]):
            # XXX if we have a heavier atom (S or SE) in the residue, some additional
            # sanity checks insure that it has slightly stronger density than we
            # require for lighter elements.  multipliers are just guesses, taking
            # into account rad damage and partial SeMet incorporation.
            heavy_atom = {
                "CYS": "SG",
                "MET": "SD",
                "MSE": "SE"
            }[main_conf.resname]
            mult = {"CYS": 1.6, "MET": 1.6, "MSE": 2.0}[main_conf.resname]
            map_levels = density_quality.density_at_atom(heavy_atom)
            if (map_levels is None):  # this probably shouldn't even happen
                skip = True
            if ((map_levels.fofc < params.map_thresholds.fofc_min * mult)
                    or (map_levels.two_fofc <
                        params.map_thresholds.two_fofc_min * mult)):
                skip = True
        n_atoms_outside_density = density_quality.show_atoms_outside_density(
            two_fofc_cutoff=params.map_thresholds.two_fofc_min,
            fofc_cutoff=params.map_thresholds.fofc_min,
            out=res_log2,
            prefix="      ")
        fofc_max = density_quality.max_fofc_value()
        if (n_atoms_outside_density > 0):
            skip = True
        if (not skip) and (verbose):
            flag = " ***"
        print("      RMSD=%5.3f  max. change=%.2f  max(Fo-Fc)=%.1f%s" \
          % (stats.rmsd, stats.max_dev, fofc_max, flag), file=res_log)
        if (changed_rotamer):
            print("      starting rotamer=%s  new rotamer=%s" % \
              (main_rotamer, best_trial.rotamer), file=res_log)
        if (n_atoms_outside_density != 0):
            print("      atoms outside density:", file=res_log)
            print(res_log2.getvalue(), file=res_log)
        else:
            print("", file=res_log)
        if (not skip) or (verbose):
            log.write(res_log.getvalue())
        if (skip): continue
        residue_group = main_conf.parent()
        main_conf.altloc = 'A'
        new_occ = 0.5
        if (params.expected_occupancy is not None):
            new_occ = max(0.2, min(0.8, params.expected_occupancy))
        for atom in main_conf.atoms():
            atom.occ = 1.0 - new_occ
            atom.segid = alt_confs.SEGID_MAIN
        new_conf = new_conf.detached_copy()
        new_conf.altloc = 'B'
        for atom in new_conf.atoms():
            atom.segid = alt_confs.SEGID_NEW_REBUILT
            atom.occ = new_occ
        residue_group.append_atom_group(new_conf)
        n_alternates += 1
    return n_alternates
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def process_results (
    pdb_hierarchy,
    fmodel,
    residues_in,
    building_trials,
    params,
    verbose=False,
    log=sys.stdout) :
  assert (len(residues_in) == len(building_trials))
  from mmtbx.rotamer import rotamer_eval
  n_alternates = 0
  unit_cell = fmodel.xray_structure.unit_cell()
  two_fofc_map, fofc_map = building.get_difference_maps(fmodel)
  rot_eval = rotamer_eval.RotamerEval(data_version="8000")
  for main_conf, trials in zip(residues_in, building_trials) :
    if (trials is None) :
      print >> log, "WARNING: error building %s" % main_conf.id_str()
      continue
    if (len(trials) == 0) :
      continue
    res_log = StringIO()
    print >> res_log, "  %s:" % main_conf.id_str()
    main_rotamer = alt_rotamer = None
    if (not main_conf.resname in ["GLY","PRO","ALA"]) :
      main_rotamer = rot_eval.evaluate_residue(main_conf)
      assert (main_rotamer != "OUTLIER")
    best_trial = pick_best_alternate(
      trials=trials,
      params=params,
      rotamer=main_rotamer,
      log=res_log)
    if (best_trial is None) :
      continue
    new_conf = best_trial.as_atom_group()
    changed_rotamer = (best_trial.rotamer != main_rotamer)
    skip = False
    flag = ""
    stats = best_trial.stats
    # FIXME this needs to be made more consistent with the filtering criteria
    # in disorder/__init__.py
    if ((stats.rmsd < params.rmsd_min) and
        (stats.max_dev < params.rmsd_min) and
        (not changed_rotamer)) :
      skip = True
    print >> res_log, "    selected conformer (occ=%.2f):" % \
      best_trial.occupancy
    res_log2 = StringIO()
    density_quality = building.residue_density_quality(
      atom_group=new_conf,
      unit_cell=unit_cell,
      two_fofc_map=two_fofc_map,
      fofc_map=fofc_map)
    if (main_conf.resname in ["CYS", "MET", "MSE"]) :
      # XXX if we have a heavier atom (S or SE) in the residue, some additional
      # sanity checks insure that it has slightly stronger density than we
      # require for lighter elements.  multipliers are just guesses, taking
      # into account rad damage and partial SeMet incorporation.
      heavy_atom = {"CYS":"SG", "MET":"SD", "MSE":"SE"}[main_conf.resname]
      mult = {"CYS":1.6, "MET":1.6, "MSE":2.0}[main_conf.resname]
      map_levels = density_quality.density_at_atom(heavy_atom)
      if (map_levels is None) : # this probably shouldn't even happen
        skip = True
      if ((map_levels.fofc < params.map_thresholds.fofc_min*mult) or
          (map_levels.two_fofc < params.map_thresholds.two_fofc_min*mult)) :
        skip = True
    n_atoms_outside_density = density_quality.show_atoms_outside_density(
      two_fofc_cutoff=params.map_thresholds.two_fofc_min,
      fofc_cutoff=params.map_thresholds.fofc_min,
      out=res_log2,
      prefix="      ")
    fofc_max = density_quality.max_fofc_value()
    if (n_atoms_outside_density > 0) :
      skip = True
    if (not skip) and (verbose) :
      flag = " ***"
    print >> res_log, \
      "      RMSD=%5.3f  max. change=%.2f  max(Fo-Fc)=%.1f%s" \
      % (stats.rmsd, stats.max_dev, fofc_max, flag)
    if (changed_rotamer) :
      print >> res_log, "      starting rotamer=%s  new rotamer=%s" % \
        (main_rotamer, best_trial.rotamer)
    if (n_atoms_outside_density != 0) :
      print >> res_log, "      atoms outside density:"
      print >> res_log, res_log2.getvalue()
    else :
      print >> res_log, ""
    if (not skip) or (verbose) :
      log.write(res_log.getvalue())
    if (skip) : continue
    residue_group = main_conf.parent()
    main_conf.altloc = 'A'
    new_occ = 0.5
    if (params.expected_occupancy is not None) :
      new_occ = max(0.2, min(0.8, params.expected_occupancy))
    for atom in main_conf.atoms() :
      atom.occ = 1.0 - new_occ
      atom.segid = alt_confs.SEGID_MAIN
    new_conf = new_conf.detached_copy()
    new_conf.altloc = 'B'
    for atom in new_conf.atoms() :
      atom.segid = alt_confs.SEGID_NEW_REBUILT
      atom.occ = new_occ
    residue_group.append_atom_group(new_conf)
    n_alternates += 1
  return n_alternates