示例#1
0
    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
示例#2
0
  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
示例#3
0
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