def get_filtered_trials(self, include_pdb_hierarchies=False, log=None):
    """
    Filter the results based on map statistics and rotamer scoring.

    :returns: a list of acceptable trial objects, or if include_pdb_hierarchies
              is True, a list of tuples of each trial and the modified pdb
              hierarchy.
    """
    if (log is None) : log = null_out()
    trials = sorted(self.get_trials(), lambda a,b: cmp(b.cc, a.cc))
    filtered = []
    for k, trial in enumerate(trials):
      hierarchy = self.pdb_hierarchy.deep_copy()
      if (trial.min_fofc < self.params.min_fofc) or (trial.cc < self.params.cc_min):
        print >> log, "  discarding trial %d [poor map quality]:" % (k+1)
        trial.show_summary(out=log, prefix="    ")
        continue
      sites = self.sites_start.deep_copy()
      sites.set_selected(self.iselection, trial.sites_cart)
      hierarchy.atoms().set_xyz(sites)
      if (self.params.filter_rotamer_outliers):
        n_outliers = alt_confs.score_rotamers(hierarchy=hierarchy,
          selection=self.iselection)
        if (n_outliers > 0):
          print >> log, "  discarding trial %d [%d rotamer outlier(s)]:" % \
            (k+1, n_outliers)
          trial.show_summary(out=log, prefix="    ")
          continue
      if (include_pdb_hierarchies):
        filtered.append((trial, hierarchy))
      else :
        filtered.append(trial)
    return filtered
Ejemplo n.º 2
0
  def get_filtered_trials (self, include_pdb_hierarchies=False, log=None) :
    """
    Filter the results based on map statistics and rotamer scoring.

    :returns: a list of acceptable trial objects, or if include_pdb_hierarchies
              is True, a list of tuples of each trial and the modified pdb
              hierarchy.
    """
    if (log is None) : log = null_out()
    trials = sorted(self.get_trials(), lambda a,b: cmp(b.cc, a.cc))
    filtered = []
    for k, trial in enumerate(trials) :
      hierarchy = self.pdb_hierarchy.deep_copy()
      if (trial.min_fofc < self.params.min_fofc) or (trial.cc < self.params.cc_min) :
        print >> log, "  discarding trial %d [poor map quality]:" % (k+1)
        trial.show_summary(out=log, prefix="    ")
        continue
      sites = self.sites_start.deep_copy()
      sites.set_selected(self.iselection, trial.sites_cart)
      hierarchy.atoms().set_xyz(sites)
      if (self.params.filter_rotamer_outliers) :
        n_outliers = alt_confs.score_rotamers(hierarchy=hierarchy,
          selection=self.iselection)
        if (n_outliers > 0) :
          print >> log, "  discarding trial %d [%d rotamer outlier(s)]:" % \
            (k+1, n_outliers)
          trial.show_summary(out=log, prefix="    ")
          continue
      if (include_pdb_hierarchies) :
        filtered.append((trial, hierarchy))
      else :
        filtered.append(trial)
    return filtered
Ejemplo n.º 3
0
def exercise_utils():
    #--- coord_stats_with_flips
    pdb_1 = iotbx.pdb.hierarchy.input(pdb_string="""\
ATOM   1639  N   PHE A 113      18.514  41.994  54.886  1.00 12.36           N
ATOM   1640  CA  PHE A 113      19.737  42.742  54.898  1.00 12.97           C
ATOM   1641  C   PHE A 113      19.514  44.206  55.111  1.00 11.88           C
ATOM   1642  O   PHE A 113      18.442  44.758  54.823  1.00 13.75           O
ATOM   1643  CB  PHE A 113      20.587  42.460  53.684  1.00 20.08           C
ATOM   1644  CG  PHE A 113      19.893  42.692  52.399  1.00 17.15           C
ATOM   1645  CD1 PHE A 113      19.182  41.689  51.798  1.00 20.34           C
ATOM   1646  CD2 PHE A 113      20.029  43.895  51.745  1.00 21.22           C
ATOM   1647  CE1 PHE A 113      18.577  41.887  50.601  1.00 23.49           C
ATOM   1648  CE2 PHE A 113      19.411  44.105  50.542  1.00 24.87           C
ATOM   1649  CZ  PHE A 113      18.675  43.097  49.976  1.00 21.81           C
ATOM   1650  H   PHE A 113      17.875  42.342  54.427  1.00 14.83           H
ATOM   1651  HA  PHE A 113      20.250  42.435  55.661  1.00 15.57           H
ATOM   1652  HB2 PHE A 113      21.367  43.036  53.708  1.00 24.10           H
ATOM   1653  HB3 PHE A 113      20.865  41.531  53.707  1.00 24.10           H
ATOM   1654  HD1 PHE A 113      19.099  40.866  52.224  1.00 24.40           H
ATOM   1655  HD2 PHE A 113      20.518  44.581  52.138  1.00 25.47           H
ATOM   1656  HE1 PHE A 113      18.077  41.204  50.215  1.00 28.18           H
ATOM   1657  HE2 PHE A 113      19.488  44.927  50.113  1.00 29.84           H
ATOM   1658  HZ  PHE A 113      18.261  43.230  49.154  1.00 26.17           H
""")
    pdb_2 = iotbx.pdb.hierarchy.input(pdb_string="""\
ATOM   1639  N   PHE A 113      18.514  41.994  54.886  1.00 12.36           N
ATOM   1640  CA  PHE A 113      19.737  42.742  54.898  1.00 12.97           C
ATOM   1641  C   PHE A 113      19.514  44.206  55.111  1.00 11.88           C
ATOM   1642  O   PHE A 113      18.442  44.758  54.823  1.00 13.75           O
ATOM   1643  CB  PHE A 113      20.587  42.460  53.684  1.00 20.08           C
ATOM   1644  CG  PHE A 113      19.893  42.692  52.399  1.00 17.15           C
ATOM   1645  CD1 PHE A 113      20.174  43.797  51.643  1.00 20.34           C
ATOM   1646  CD2 PHE A 113      18.888  41.845  51.991  1.00 21.22           C
ATOM   1647  CE1 PHE A 113      19.512  44.033  50.483  1.00 23.49           C
ATOM   1648  CE2 PHE A 113      18.224  42.071  50.816  1.00 24.87           C
ATOM   1649  CZ  PHE A 113      18.548  43.166  50.057  1.00 21.81           C
ATOM   1650  H   PHE A 113      17.875  42.342  54.427  1.00 14.83           H
ATOM   1651  HA  PHE A 113      20.250  42.435  55.661  1.00 15.57           H
ATOM   1652  HB2 PHE A 113      21.367  43.036  53.708  1.00 24.10           H
ATOM   1653  HB3 PHE A 113      20.865  41.531  53.707  1.00 24.10           H
ATOM   1654  HD1 PHE A 113      20.840  44.386  51.919  1.00 24.40           H
ATOM   1655  HD2 PHE A 113      18.681  41.096  52.501  1.00 25.47           H
ATOM   1656  HE1 PHE A 113      19.730  44.776  49.967  1.00 28.18           H
ATOM   1657  HE2 PHE A 113      17.560  41.484  50.533  1.00 29.84           H
ATOM   1658  HZ  PHE A 113      18.093  43.330  49.263  1.00 26.17           H
""")
    hierarchy_1 = pdb_1.hierarchy
    hierarchy_2 = pdb_2.hierarchy
    pdb_atoms_1 = hierarchy_1.atoms()
    sites_1 = pdb_atoms_1.extract_xyz()
    sites_2 = hierarchy_2.atoms().extract_xyz()
    result = alternate_conformations.coord_stats_with_flips(
        sites_1, sites_2, pdb_atoms_1)
    assert (approx_equal(result.rmsd, 0.2, eps=0.001))
    assert (approx_equal(result.max_dev, 0.452427, eps=0.00001))
    #--- get_selection_gap
    assert (alternate_conformations.get_selection_gap([1, 2, 3, 4, 5],
                                                      [6, 7, 8, 9]) == 0)
    assert (alternate_conformations.get_selection_gap([6, 7],
                                                      [1, 2, 3, 4, 5]) == 0)
    assert (alternate_conformations.get_selection_gap([1, 2, 3, 4, 5],
                                                      [7, 8, 9]) == 1)
    assert (alternate_conformations.get_selection_gap([1, 2, 3, 4, 5],
                                                      [4, 5, 7, 8, 9]) == -2)
    assert (alternate_conformations.get_selection_gap([4, 5, 7, 8, 9],
                                                      [1, 2, 3, 4]) == -1)
    #--- score_rotamers
    n_outliers = alternate_conformations.score_rotamers(
        hierarchy_2, flex.bool(sites_2.size(), True))
    assert (n_outliers == 0)
    #--- get_partial_omit_map
    xrs = pdb_1.input.xray_structure_simple()
    f_calc = abs(xrs.structure_factors(d_min=1.5).f_calc())
    f_calc.set_observation_type_xray_amplitude()
    flags = f_calc.generate_r_free_flags()
    fmodel = mmtbx.utils.fmodel_simple(xray_structures=[xrs],
                                       f_obs=f_calc,
                                       r_free_flags=flags,
                                       scattering_table="n_gaussian",
                                       bulk_solvent_and_scaling=False,
                                       skip_twin_detection=True)
    sel = pdb_1.hierarchy.atom_selection_cache().selection("name CZ")
    assert (sel.count(True) == 1)
    two_fofc_map, fofc_map = alternate_conformations.get_partial_omit_map(
        fmodel=fmodel, selection=sel)
    site = xrs.sites_frac()[sel.iselection()[0]]  # CZ coordinate
    assert (fofc_map.tricubic_interpolation(site) > 20)
Ejemplo n.º 4
0
def exercise_utils () :
  #--- coord_stats_with_flips
  pdb_1 = iotbx.pdb.hierarchy.input(pdb_string="""\
ATOM   1639  N   PHE A 113      18.514  41.994  54.886  1.00 12.36           N
ATOM   1640  CA  PHE A 113      19.737  42.742  54.898  1.00 12.97           C
ATOM   1641  C   PHE A 113      19.514  44.206  55.111  1.00 11.88           C
ATOM   1642  O   PHE A 113      18.442  44.758  54.823  1.00 13.75           O
ATOM   1643  CB  PHE A 113      20.587  42.460  53.684  1.00 20.08           C
ATOM   1644  CG  PHE A 113      19.893  42.692  52.399  1.00 17.15           C
ATOM   1645  CD1 PHE A 113      19.182  41.689  51.798  1.00 20.34           C
ATOM   1646  CD2 PHE A 113      20.029  43.895  51.745  1.00 21.22           C
ATOM   1647  CE1 PHE A 113      18.577  41.887  50.601  1.00 23.49           C
ATOM   1648  CE2 PHE A 113      19.411  44.105  50.542  1.00 24.87           C
ATOM   1649  CZ  PHE A 113      18.675  43.097  49.976  1.00 21.81           C
ATOM   1650  H   PHE A 113      17.875  42.342  54.427  1.00 14.83           H
ATOM   1651  HA  PHE A 113      20.250  42.435  55.661  1.00 15.57           H
ATOM   1652  HB2 PHE A 113      21.367  43.036  53.708  1.00 24.10           H
ATOM   1653  HB3 PHE A 113      20.865  41.531  53.707  1.00 24.10           H
ATOM   1654  HD1 PHE A 113      19.099  40.866  52.224  1.00 24.40           H
ATOM   1655  HD2 PHE A 113      20.518  44.581  52.138  1.00 25.47           H
ATOM   1656  HE1 PHE A 113      18.077  41.204  50.215  1.00 28.18           H
ATOM   1657  HE2 PHE A 113      19.488  44.927  50.113  1.00 29.84           H
ATOM   1658  HZ  PHE A 113      18.261  43.230  49.154  1.00 26.17           H
""")
  pdb_2 = iotbx.pdb.hierarchy.input(pdb_string="""\
ATOM   1639  N   PHE A 113      18.514  41.994  54.886  1.00 12.36           N
ATOM   1640  CA  PHE A 113      19.737  42.742  54.898  1.00 12.97           C
ATOM   1641  C   PHE A 113      19.514  44.206  55.111  1.00 11.88           C
ATOM   1642  O   PHE A 113      18.442  44.758  54.823  1.00 13.75           O
ATOM   1643  CB  PHE A 113      20.587  42.460  53.684  1.00 20.08           C
ATOM   1644  CG  PHE A 113      19.893  42.692  52.399  1.00 17.15           C
ATOM   1645  CD1 PHE A 113      20.174  43.797  51.643  1.00 20.34           C
ATOM   1646  CD2 PHE A 113      18.888  41.845  51.991  1.00 21.22           C
ATOM   1647  CE1 PHE A 113      19.512  44.033  50.483  1.00 23.49           C
ATOM   1648  CE2 PHE A 113      18.224  42.071  50.816  1.00 24.87           C
ATOM   1649  CZ  PHE A 113      18.548  43.166  50.057  1.00 21.81           C
ATOM   1650  H   PHE A 113      17.875  42.342  54.427  1.00 14.83           H
ATOM   1651  HA  PHE A 113      20.250  42.435  55.661  1.00 15.57           H
ATOM   1652  HB2 PHE A 113      21.367  43.036  53.708  1.00 24.10           H
ATOM   1653  HB3 PHE A 113      20.865  41.531  53.707  1.00 24.10           H
ATOM   1654  HD1 PHE A 113      20.840  44.386  51.919  1.00 24.40           H
ATOM   1655  HD2 PHE A 113      18.681  41.096  52.501  1.00 25.47           H
ATOM   1656  HE1 PHE A 113      19.730  44.776  49.967  1.00 28.18           H
ATOM   1657  HE2 PHE A 113      17.560  41.484  50.533  1.00 29.84           H
ATOM   1658  HZ  PHE A 113      18.093  43.330  49.263  1.00 26.17           H
""")
  hierarchy_1 = pdb_1.hierarchy
  hierarchy_2 = pdb_2.hierarchy
  pdb_atoms_1 = hierarchy_1.atoms()
  sites_1 = pdb_atoms_1.extract_xyz()
  sites_2 = hierarchy_2.atoms().extract_xyz()
  result = alternate_conformations.coord_stats_with_flips(sites_1, sites_2, pdb_atoms_1)
  assert (approx_equal(result.rmsd, 0.2, eps=0.001))
  assert (approx_equal(result.max_dev, 0.452427, eps=0.00001))
  #--- get_selection_gap
  assert (alternate_conformations.get_selection_gap([1,2,3,4,5],[6,7,8,9]) == 0)
  assert (alternate_conformations.get_selection_gap([6,7], [1,2,3,4,5]) == 0)
  assert (alternate_conformations.get_selection_gap([1,2,3,4,5],[7,8,9]) == 1)
  assert (alternate_conformations.get_selection_gap([1,2,3,4,5],[4,5,7,8,9]) == -2)
  assert (alternate_conformations.get_selection_gap([4,5,7,8,9],[1,2,3,4]) == -1)
  #--- score_rotamers
  n_outliers = alternate_conformations.score_rotamers(hierarchy_2,
    flex.bool(sites_2.size(), True))
  assert (n_outliers == 0)
  #--- get_partial_omit_map
  xrs = pdb_1.input.xray_structure_simple()
  f_calc = abs(xrs.structure_factors(d_min=1.5).f_calc())
  f_calc.set_observation_type_xray_amplitude()
  flags = f_calc.generate_r_free_flags()
  fmodel = mmtbx.utils.fmodel_simple(
    xray_structures=[xrs],
    f_obs=f_calc,
    r_free_flags=flags,
    scattering_table="n_gaussian",
    bulk_solvent_and_scaling=False,
    skip_twin_detection=True)
  sel = pdb_1.hierarchy.atom_selection_cache().selection("name CZ")
  assert (sel.count(True) == 1)
  two_fofc_map, fofc_map = alternate_conformations.get_partial_omit_map(
    fmodel=fmodel,
    selection=sel)
  site = xrs.sites_frac()[sel.iselection()[0]] # CZ coordinate
  assert (fofc_map.tricubic_interpolation(site) > 20)
Ejemplo n.º 5
0
 def __init__(self,
     fmodel,
     params,
     mp_params,
     pdb_hierarchy,
     processed_pdb_file,
     selection=None,
     cif_objects=(),
     verbose=True,
     debug=False,
     out=None):
   if (out is None) : out = sys.stdout
   adopt_init_args(self, locals())
   self.asynchronous_output = False
   from mmtbx.rotamer import rotamer_eval
   from scitbx.array_family import flex
   assert (processed_pdb_file is not None) or (len(pdb_file_names) > 0)
   assert (0 < self.params.window_radius <= 4)
   self.pdb_hierarchy = pdb_hierarchy
   self.processed_pdb_file = processed_pdb_file
   self.get_processed_pdb_file(log=out)
   self.sites_cart = self.pdb_hierarchy.atoms().extract_xyz().deep_copy()
   if (self.selection is None):
     self.selection = flex.bool(self.sites_cart.size(), True)
   self.min_required_deviation = self.params.min_deviation
   if (self.min_required_deviation is Auto):
     self.min_required_deviation = fmodel.f_obs().d_min() / 2
   self._ensembles = []
   self.nproc_1 = self.nproc_2 = 1
   two_fofc_map, fofc_map = mmtbx.building.get_difference_maps(fmodel=fmodel)
   windows = []
   r = rotamer_eval.RotamerEval(data_version="8000")
   exclude_resnames = []
   if (params.exclude_resnames is not None):
     exclude_resnames = [ n.upper() for n in params.exclude_resnames ]
   for chain in self.pdb_hierarchy.only_model().chains():
     if not chain.is_protein():
       continue
     residues = chain.residue_groups()
     fragments = alt_confs.fragment_single_conformer_chain(residues)
     for fragment_residues in fragments :
       start = params.window_radius
       end = - params.window_radius
       for i_res, residue in enumerate(fragment_residues[start:end]):
         j_res = i_res + start
         atom_groups = residue.atom_groups()
         main_conf = atom_groups[0]
         if (main_conf.resname.upper() in exclude_resnames):
           continue
         residue_id = main_conf.id_str()
         ag_i_seqs = main_conf.atoms().extract_i_seq()
         if (not self.selection.select(ag_i_seqs).all_eq(True)):
           continue
         if (len(atom_groups) != 1):
           if (self.verbose):
             print("  residue %s already has multiple conformations"%\
               residue_id, file=out)
           continue
         ag_i_seqs_no_hd = flex.size_t()
         for atom in main_conf.atoms():
           if (atom.element.strip() not in ["H","D"]):
             ag_i_seqs_no_hd.append(atom.i_seq)
         # XXX this is probably not optimal; what should I do about the
         # adjacent residues?  it would be good to check Ramachandran plot too
         if (self.params.prefilter.rotameric_only):
           n_outliers = alt_confs.score_rotamers(hierarchy=hierarchy,
             selection=ag_i_seqs)
           if (n_outliers > 0):
             if (self.verbose):
               print("  residue %s is a rotamer outlier" % residue_id, file=out)
             continue
         if (self.params.prefilter.use_difference_map):
           map_stats = building.local_density_quality(
             fofc_map=fofc_map,
             two_fofc_map=two_fofc_map,
             atom_selection=ag_i_seqs_no_hd,
             xray_structure=fmodel.xray_structure,
             radius=self.params.prefilter.sampling_radius)
           if ((map_stats.number_of_atoms_in_difference_holes() == 0) and
               (map_stats.fraction_of_nearby_grid_points_above_cutoff()==0)):
             if (self.verbose):
               print("  no difference density for %s" % residue_id, file=out)
             continue
         window_selection = flex.size_t()
         offset = - self.params.window_radius
         while (offset <= self.params.window_radius):
           adjacent_group = fragment_residues[j_res+offset].atom_groups()[0]
           window_selection.extend(adjacent_group.atoms().extract_i_seq())
           offset += 1
         windows.append(residue_window(
           residue_id_str=residue_id,
           selection=window_selection,
           residue_selection=ag_i_seqs_no_hd,
           sites_reference=self.sites_cart.select(selection),
           window_radius=self.params.window_radius))
   if (len(windows) == 0):
     raise Sorry("No peptide segments meeting the filtering criteria could "+
       "be extracted from the selected atoms.")
   else :
     print("%d fragments will be refined." % len(windows), file=out)
   if (self.mp_params.nproc == 1):
     pass
   elif (self.mp_params.technology == "multiprocessing"):
     if (self.params.n_trials == 1) and (len(self.params.partial_occupancy) == 1):
       # only one refinement per window, so parallelize residue iteration
       self.nproc_1 = self.mp_params.nproc
     else :
       # multiple refinements per window, so parallelize at that level
       # FIXME actually, this needs to be smarter - if the number of
       # available processors is greater than the number of refinements per
       # window, it will be more efficient to parallelize the window loop
       self.nproc_2 = self.mp_params.nproc
   else :
     # queuing system, so we can only parallelize residue iteration
     self.nproc_1 = self.mp_params.nproc
     self.out = null_out()
     self.processed_pdb_file = None
   print("", file=out)
   alt_confs.print_trial_header(out)
   ensembles = []
   if (self.nproc_1 == 1):
     self.asynchronous_output = True
     for window in windows :
       ens = self.refine_window(window)
       ensembles.append(ens)
   else :
     ensembles = easy_mp.parallel_map(
       func=self.refine_window,
       iterable=windows,
       processes=self.nproc_1,
       qsub_command=mp_params.qsub_command,
       method=mp_params.technology)
   self._ensembles = [ e for e in ensembles if (e is not None) ]
   # XXX reassert order
   print("", file=out)
   if (len(self._ensembles) == 0):
     print("WARNING: no ensembles passed filtering step", file=out)
     print("", file=out)
   self._ensembles.sort(lambda a,b: a.selection[0] < b.selection[0])
   self.processed_pdb_file = processed_pdb_file
   if (debug):
     for k, ens in enumerate(filtered):
       pdb_out = ens.dump_pdb_file(
         pdb_hierarchy=pdb_hierarchy,
         crystal_symmetry=fmodel.f_obs())
       print("wrote %s" % pdb_out, file=out)
Ejemplo n.º 6
0
 def __init__ (self,
     fmodel,
     params,
     mp_params,
     pdb_hierarchy,
     processed_pdb_file,
     selection=None,
     cif_objects=(),
     verbose=True,
     debug=False,
     out=None) :
   if (out is None) : out = sys.stdout
   adopt_init_args(self, locals())
   self.asynchronous_output = False
   from mmtbx.rotamer import rotamer_eval
   from scitbx.array_family import flex
   assert (processed_pdb_file is not None) or (len(pdb_file_names) > 0)
   assert (0 < self.params.window_radius <= 4)
   self.pdb_hierarchy = pdb_hierarchy
   self.processed_pdb_file = processed_pdb_file
   self.get_processed_pdb_file(log=out)
   self.sites_cart = self.pdb_hierarchy.atoms().extract_xyz().deep_copy()
   if (self.selection is None) :
     self.selection = flex.bool(self.sites_cart.size(), True)
   self.min_required_deviation = self.params.min_deviation
   if (self.min_required_deviation is Auto) :
     self.min_required_deviation = fmodel.f_obs().d_min() / 2
   self._ensembles = []
   self.nproc_1 = self.nproc_2 = 1
   two_fofc_map, fofc_map = mmtbx.building.get_difference_maps(fmodel=fmodel)
   windows = []
   r = rotamer_eval.RotamerEval(data_version="8000")
   exclude_resnames = []
   if (params.exclude_resnames is not None) :
     exclude_resnames = [ n.upper() for n in params.exclude_resnames ]
   for chain in self.pdb_hierarchy.only_model().chains() :
     main_conf = chain.conformers()[0]
     if (not main_conf.is_protein()) :
       continue
     residues = chain.residue_groups()
     fragments = alt_confs.fragment_single_conformer_chain(residues)
     for fragment_residues in fragments :
       start = params.window_radius
       end = - params.window_radius
       for i_res, residue in enumerate(fragment_residues[start:end]) :
         j_res = i_res + start
         atom_groups = residue.atom_groups()
         main_conf = atom_groups[0]
         if (main_conf.resname.upper() in exclude_resnames) :
           continue
         residue_id = main_conf.id_str()
         ag_i_seqs = main_conf.atoms().extract_i_seq()
         if (not self.selection.select(ag_i_seqs).all_eq(True)) :
           continue
         if (len(atom_groups) != 1) :
           if (self.verbose) :
             print >> out, "  residue %s already has multiple conformations"%\
               residue_id
           continue
         ag_i_seqs_no_hd = flex.size_t()
         for atom in main_conf.atoms() :
           if (atom.element.strip() not in ["H","D"]) :
             ag_i_seqs_no_hd.append(atom.i_seq)
         # XXX this is probably not optimal; what should I do about the
         # adjacent residues?  it would be good to check Ramachandran plot too
         if (self.params.prefilter.rotameric_only) :
           n_outliers = alt_confs.score_rotamers(hierarchy=hierarchy,
             selection=ag_i_seqs)
           if (n_outliers > 0) :
             if (self.verbose) :
               print >> out, "  residue %s is a rotamer outlier" % residue_id
             continue
         if (self.params.prefilter.use_difference_map) :
           map_stats = building.local_density_quality(
             fofc_map=fofc_map,
             two_fofc_map=two_fofc_map,
             atom_selection=ag_i_seqs_no_hd,
             xray_structure=fmodel.xray_structure,
             radius=self.params.prefilter.sampling_radius)
           if ((map_stats.number_of_atoms_in_difference_holes() == 0) and
               (map_stats.fraction_of_nearby_grid_points_above_cutoff()==0)) :
             if (self.verbose) :
               print >> out, "  no difference density for %s" % residue_id
             continue
         window_selection = flex.size_t()
         offset = - self.params.window_radius
         while (offset <= self.params.window_radius) :
           adjacent_group = fragment_residues[j_res+offset].atom_groups()[0]
           window_selection.extend(adjacent_group.atoms().extract_i_seq())
           offset += 1
         windows.append(residue_window(
           residue_id_str=residue_id,
           selection=window_selection,
           residue_selection=ag_i_seqs_no_hd,
           sites_reference=self.sites_cart.select(selection),
           window_radius=self.params.window_radius))
   if (len(windows) == 0) :
     raise Sorry("No peptide segments meeting the filtering criteria could "+
       "be extracted from the selected atoms.")
   else :
     print >> out, "%d fragments will be refined." % len(windows)
   if (self.mp_params.nproc == 1) :
     pass
   elif (self.mp_params.technology == "multiprocessing") :
     if (self.params.n_trials == 1) and (len(self.params.partial_occupancy) == 1) :
       # only one refinement per window, so parallelize residue iteration
       self.nproc_1 = self.mp_params.nproc
     else :
       # multiple refinements per window, so parallelize at that level
       # FIXME actually, this needs to be smarter - if the number of
       # available processors is greater than the number of refinements per
       # window, it will be more efficient to parallelize the window loop
       self.nproc_2 = self.mp_params.nproc
   else :
     # queuing system, so we can only parallelize residue iteration
     self.nproc_1 = self.mp_params.nproc
     self.out = null_out()
     self.processed_pdb_file = None
   print >> out, ""
   alt_confs.print_trial_header(out)
   ensembles = []
   if (self.nproc_1 == 1) :
     self.asynchronous_output = True
     for window in windows :
       ens = self.refine_window(window)
       ensembles.append(ens)
   else :
     ensembles = easy_mp.parallel_map(
       func=self.refine_window,
       iterable=windows,
       processes=self.nproc_1,
       qsub_command=mp_params.qsub_command,
       method=mp_params.technology)
   self._ensembles = [ e for e in ensembles if (e is not None) ]
   # XXX reassert order
   print >> out, ""
   if (len(self._ensembles) == 0) :
     print >> out, "WARNING: no ensembles passed filtering step"
     print >> out, ""
   self._ensembles.sort(lambda a,b: a.selection[0] < b.selection[0])
   self.processed_pdb_file = processed_pdb_file
   if (debug) :
     for k, ens in enumerate(filtered) :
       pdb_out = ens.dump_pdb_file(
         pdb_hierarchy=pdb_hierarchy,
         crystal_symmetry=fmodel.f_obs())
       print >> out, "wrote %s" % pdb_out