diff --git a/cctbx/geometry_restraints/auto_linking_types.py b/cctbx/geometry_restraints/auto_linking_types.py index ac4af2275f..45ec35caa4 100644 --- a/cctbx/geometry_restraints/auto_linking_types.py +++ b/cctbx/geometry_restraints/auto_linking_types.py @@ -99,8 +99,14 @@ def __repr__(self): [None, None, None, None, None, 'Basepair parallelity'], [5], ], + ['side-chain parallelity', + 'Enforces parallel between two alt conf side-chains', + 'JH', + [None, None, None, None, None, 'Side-chain parallelity'], + [5], + ], ['basepair planarity', - 'Enforces planrity of two base pairs in paired bases', + 'Enforces planarity of two base pairs in paired bases', 'J. Appl. Cryst. 48, 1130-1141 (2015).', [None, None, None, 'xxx', 'Basepair planarity'], [3], diff --git a/cctbx/geometry_restraints/manager.py b/cctbx/geometry_restraints/manager.py index 6a6e4d9fdd..b952d50e27 100644 --- a/cctbx/geometry_restraints/manager.py +++ b/cctbx/geometry_restraints/manager.py @@ -23,6 +23,36 @@ origin_ids = linking_class() from cctbx.geometry_restraints.base_geometry import Base_geometry +def create_side_chain_restraints(hierarchy, grm, log=None): + proxies=[] + for rg in hierarchy.residue_groups(): + ags=rg.atom_groups() + names = [] + for atom in rg.atoms(): + if atom.element_is_hydrogen(): continue + if atom.name not in names: + names.append(atom.name) + pairs=[[],[]] + for name in names: + if name in [' CA ', ' N ', ' C ', ' O ']: continue + for i, ag in enumerate(ags): + if not ag.altloc: continue + pairs[i].append(ag.get_atom(name.strip()).i_seq) + sigma=.2 + if not pairs[0] or not pairs[1]: continue + if len(pairs[0])<3 or len(pairs[1])<3: continue + proxy=geometry_restraints.parallelity_proxy( + i_seqs=flex.size_t(pairs[0]), + j_seqs=flex.size_t(pairs[1]), + weight=1/(sigma**2), + target_angle_deg=0, + slack=0, + top_out=False, + limit=1, + origin_id=origin_ids.get_origin_id('side-chain parallelity')) + proxies.append(proxy) + return proxies + class manager(Base_geometry): # This class is documented in # http://www.phenix-online.org/papers/iucrcompcomm_aug2004.pdf @@ -873,6 +903,12 @@ def remove_secondary_structure_restraints(self): # of bond restraint. raise NotImplementedError + def add_parallelity_proxies_for_side_chain(self, hierarchy, log): + parallelity_proxies = create_side_chain_restraints( hierarchy=hierarchy, + grm=self, + log=log) + self.add_parallelities_in_place(parallelity_proxies) + def set_external_energy_function(self, energy_function): self.external_energy_function = energy_function @@ -1754,7 +1790,7 @@ def show_sorted(self, ('Reference coordinate', self.reference_coordinate_proxies), ]: if proxies is not None: - if hasattr(pair_proxies, 'show_sorted'): + if hasattr(proxies, 'show_sorted'): proxies.show_sorted( by_value="residual", sites_cart=sites_cart, diff --git a/mmtbx/monomer_library/pdb_interpretation.py b/mmtbx/monomer_library/pdb_interpretation.py index da9597b7ec..af5234aa89 100644 --- a/mmtbx/monomer_library/pdb_interpretation.py +++ b/mmtbx/monomer_library/pdb_interpretation.py @@ -273,6 +273,11 @@ def __init__(self, residue_name, atom_name, atom_element): .help = Sets the reference coordinate to the average of two alt. confs. \ Ignores selection option. } + automatic_restraints + { + side_chain_parallelity = False + .type = bool + } automatic_linking .style = box auto_align noauto .short_caption = Automatic covalent linking @@ -6105,6 +6110,11 @@ def geometry_restraints_manager(self, print(" Number of reference coordinate restraints generated:",\ n_rcr, file=self.log) + if self.all_chain_proxies.params.automatic_restraints.side_chain_parallelity: + self._geometry_restraints_manager.\ + add_parallelity_proxies_for_side_chain(self.all_chain_proxies.pdb_hierarchy, + log=self.log) + # DEN manager self._geometry_restraints_manager.adopt_den_manager(den_manager)