From 351af37eef60a02792f6376d5b6ffd1a1a31dc5f Mon Sep 17 00:00:00 2001 From: Pavel Date: Fri, 8 May 2020 13:00:54 -0700 Subject: [PATCH] Severe bug fix: arrays of different length were passed into C++ code; it would not crash but produce wrong and very hard to debug results! --- mmtbx/refinement/real_space/__init__.py | 33 +++++++++++----- mmtbx/refinement/real_space/fit_residue.py | 42 ++++++++++----------- mmtbx/refinement/real_space/fit_residues.py | 4 +- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/mmtbx/refinement/real_space/__init__.py b/mmtbx/refinement/real_space/__init__.py index 27ad3d9295..5009bb7a4d 100644 --- a/mmtbx/refinement/real_space/__init__.py +++ b/mmtbx/refinement/real_space/__init__.py @@ -172,6 +172,27 @@ def flatten(l): if l is None: return None return sum(([x] if not (isinstance(x, list) or isinstance(x, flex.size_t)) else flatten(x) for x in l), []) +def get_radii(residue, vdw_radii): + atom_names = [a.name.strip() for a in residue.atoms()] + converter = iotbx.pdb.residue_name_plus_atom_names_interpreter( + residue_name = residue.resname, atom_names = atom_names) + mon_lib_names = converter.atom_name_interpretation.mon_lib_names() + radii = flex.double() + for n in mon_lib_names: + try: radii.append(vdw_radii[n.strip()]-0.25) + except KeyError: radii.append(1.5) # XXX U, Uranium, OXT are problems! + return radii + +def get_radius(atom, vdw_radii): + atom_names = [atom.name.strip()] + converter = iotbx.pdb.residue_name_plus_atom_names_interpreter( + residue_name = atom.parent().resname, atom_names = atom_names) + if(converter.atom_name_interpretation is not None): + atom_names = converter.atom_name_interpretation.mon_lib_names() + n = atom_names[0].strip() + try: return vdw_radii[n.strip()]-0.25 + except KeyError: return 1.5 # XXX U, Uranium, OXT are problems! + def common_map_values(pdb_hierarchy, unit_cell, map_data): d = {} for model in pdb_hierarchy.models(): @@ -199,16 +220,8 @@ def mean_filtered(x): overall_mean = flex.mean_default(all_vals.select(sel),0) for k,v in zip(d.keys(), d.values()): sel = mean_filtered(v) - if(sel.count(True)>10): - result[k] = flex.mean_default(v.select(sel),0) - else: - result[k] = overall_mean - an = key.split("_")[-1][0] - mv = flex.mean_default(v,0) - if(an=="S"): - result[k] = mv - else: - result[k] = overall_mean + if(sel.count(True)>10): result[k] = flex.mean_default(v.select(sel),0) + else: result[k] = overall_mean return result class side_chain_fit_evaluator(object): diff --git a/mmtbx/refinement/real_space/fit_residue.py b/mmtbx/refinement/real_space/fit_residue.py index b3f8769ecf..093d645e7f 100644 --- a/mmtbx/refinement/real_space/fit_residue.py +++ b/mmtbx/refinement/real_space/fit_residue.py @@ -7,7 +7,6 @@ from cctbx import maptbx import scitbx.math import mmtbx.idealized_aa_residues.rotamer_manager -import iotbx.pdb import collections from libtbx import group_args @@ -214,35 +213,34 @@ def fit_side_chain(self, clusters): cl = clusters[i] axes.append(flex.size_t(cl.axis)) atr.append(flex.size_t(cl.atoms_to_rotate)) - sites = self.residue.atoms().extract_xyz() + # if(self.target_map is not None and self.xyzrad_bumpers is not None): - # Get vdW radii - offset = 0.25 - #if(self.residue.resname=="MSE"): offset=0.5 - radii = flex.double() - atom_names = [] + # Get reference map values ref_map_vals = flex.double() for a in self.residue.atoms(): - if(self.rotatable_hd[a.i_seq]): continue # don't include rotatable H - atom_names.append(a.name.strip()) key = "%s_%s_%s"%( a.parent().parent().parent().id, a.parent().resname, a.name.strip()) ref_map_vals.append(self.cmv[key]) - converter = iotbx.pdb.residue_name_plus_atom_names_interpreter( - residue_name=self.residue.resname, atom_names = atom_names) - mon_lib_names = converter.atom_name_interpretation.mon_lib_names() - for n in mon_lib_names: - try: radii.append(self.vdw_radii[n.strip()]-offset) - except KeyError: radii.append(1.5) # XXX U, Uranium, OXT are problems! - # - xyzrad_residue = ext.moving( - sites_cart = sites, + # Get radii + radii = mmtbx.refinement.real_space.get_radii( + residue = self.residue, vdw_radii = self.vdw_radii) + # Exclude rotatable H from clash calculation + tmp = flex.size_t() + for i in selection_clash: + if(self.rotatable_hd[self.residue.atoms()[i].i_seq]): continue + tmp.append(i) + selection_clash = tmp[:] + # Ad hoc: S or SE have larger peaks! + if(self.residue.resname in ["MET","MSE"]): scale=100 + else: scale=3 + moving = ext.moving( + sites_cart = self.residue.atoms().extract_xyz(), sites_cart_start = sites_cart_start, radii = radii, weights = self.weights, bonded_pairs = self.pairs, - ref_map_max = ref_map_vals * 3, + ref_map_max = ref_map_vals * scale, ref_map_min = ref_map_vals / 10) # ro = ext.fit( @@ -251,10 +249,10 @@ def fit_side_chain(self, clusters): rotatable_points_indices = atr, angles_array = self.chi_angles, density_map = self.target_map, - moving = xyzrad_residue, + moving = moving, unit_cell = self.unit_cell, selection_clash = selection_clash, - selection_rsr = selection_rsr, + selection_rsr = selection_rsr, # select atoms to compute map target sin_table = self.sin_cos_table.sin_table, cos_table = self.sin_cos_table.cos_table, step = self.sin_cos_table.step, @@ -266,7 +264,7 @@ def fit_side_chain(self, clusters): rotatable_points_indices = atr, angles_array = self.chi_angles, density_map = self.target_map, - all_points = sites, + all_points = self.residue.atoms().extract_xyz(), unit_cell = self.unit_cell, selection = selection_rsr, sin_table = self.sin_cos_table.sin_table, diff --git a/mmtbx/refinement/real_space/fit_residues.py b/mmtbx/refinement/real_space/fit_residues.py index 99df5ab6bc..68cf7656e0 100644 --- a/mmtbx/refinement/real_space/fit_residues.py +++ b/mmtbx/refinement/real_space/fit_residues.py @@ -127,8 +127,8 @@ def get_nonbonded_bumpers(self, residue, radius): for i in selection_around_residue_minus_residue_minus_rotatableH: atom = self.atoms[i] an = atom.name.strip() - try: rad = self.vdw_radii[an]-0.25 - except KeyError: rad = 1.5 # XXX U, Uranium, OXT are problems! + rad = mmtbx.refinement.real_space.get_radius( + atom = atom, vdw_radii = self.vdw_radii) good = True if(self.diff_map_data is not None): sf = self.crystal_symmetry.unit_cell().fractionalize(atom.xyz)