1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
|
import types
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk
import coot
import coot_utils
import coot_gui
import res_spec_utils
import redefine_functions as rdf
# consider for coot_utils
def residue_spec_to_string(spec):
# print("DEBUG:: in residue_spec_to_string() with spec", spec)
if len(spec) == 4:
return (spec[1] + str(spec[2]) + spec[3])
else:
return (spec[0] + str(spec[1]) + spec[2])
# find bad things in the structure - rama, C-beta, rotamer, atom clashes baddies
#
def validation_outliers_dialog(imol, imol_map):
dialog_vbox = False
window = False
missing_sidechains_checkbutton = False
cg_torsion_diff_checkbutton = False
poor_density_checkbutton = False
def find_rama_baddies():
rs = coot.all_molecule_ramachandran_score_py(imol)
scored_residues = rs[5]
interesting = filter(lambda item: item[2] < 0.02, scored_residues)
# remove phi-psi and res-names from the return value
munged = map(lambda item: [item[1], item[2]], interesting)
return ["Ramachandran Improbables", munged]
# a list of atom specs
def find_chiral_volume_baddies():
r = coot.chiral_volume_errors_py(imol)
if not isinstance(r, list):
return []
else:
return r
def make_window_title(n):
return "Coot Interesting/Outliers/Problems: " + str(n)
def find_c_beta_baddies():
try:
c_beta_deviations
except:
return []
return c_beta_deviations(imol)
def find_em_ringer_baddies():
try:
CG_spin_research
except:
return []
if not isinstance(scored_residues, list):
return []
else:
scored_residues = CG_spin_research(imol, imol_map)
interesting = filter(lambda item: item[1] > 30 or item[1] < -30,
scored_residues)
# return a list of residue specs - not what is expected?
return interesting
def rotamer_score_residues(imol):
residues = coot_utils.all_residues_sans_water(imol)
ret = map(lambda residue_spec: [residue_spec,
coot.rotamer_score(imol,
res_spec_utils.residue_spec_to_chain_id(residue_spec),
res_spec_utils.residue_spec_to_res_no(residue_spec),
coot_utils.residue_spec_to_ins_code(residue_spec),
"")],
residues)
return ret
def filter_rotamer_baddies(baddies):
het_groups_in_mol = coot.het_group_residues_py(imol)
ret = []
for baddie in baddies:
spec, score = baddie
res_name = coot.residue_name(imol,
res_spec_utils.residue_spec_to_chain_id(spec),
res_spec_utils.residue_spec_to_res_no(spec),
coot_utils.residue_spec_to_ins_code(spec))
if res_name in ["ALA", "GLY", "UNK", "HOH"]:
pass
elif (score == 0.0 and not ok_to_have_missing_sidechain_buttons_qm()):
pass
else:
# if spec is a het-group then no rotamers for that (return False)
is_het = any(map(lambda item: residue_specs_match_qm(item, spec),
het_groups_in_mol))
if is_het:
pass
else:
if res_name == "LEU":
if score < 1.1:
ret += [baddie]
else:
if score < 0.021:
ret += [baddie]
return ret
def molecule_atom_overlap_baddies():
l = coot.molecule_atom_overlaps_py(imol)
if isinstance(l, list):
return l
else:
info_dialog(l)
return []
def filter_molecule_atom_overlap_baddies(mao_baddies):
baddie_limit = 2.0 # more than this is marked as a baddie, was 2.2. Is 2.0 good?
return filter(lambda mao_item: mao_item['overlap-volume'] > baddie_limit, mao_baddies)
def non_pro_cis_peptide_baddies(): # do the filter here - just for consistency
cis_peps = coot.cis_peptides_py(imol)
return filter(lambda peptide: "PRO" != coot_utils.residue_spec_to_residue_name(imol, peptide[1]), cis_peps)
def twisted_trans_peptide_baddies():
return coot.twisted_trans_peptides_py(imol)
def destroy_buttons_with_label(label_fragment_txt, dialog_vbox):
current_buttons = dialog_vbox.get_children()
for button in current_buttons:
label = button.get_label()
if label_fragment_txt in label:
button.destroy()
def regenerate_button_fn(*args):
def cb_func(button, callback):
callback("some-arg")
if dialog_vbox:
old_buttons = dialog_vbox.get_children()
for butt in old_buttons:
butt.destroy()
buttons = make_buttons()
for button_parts in buttons:
# print("button parts 0", button_parts[0])
# print("button parts 1", button_parts[1])
button = Gtk.Button(button_parts[0])
button.connect("clicked", cb_func, button_parts[1])
dialog_vbox.append(button)
button.show()
if window:
window.set_title(make_window_title(len(buttons)))
# validation_outliers_dialog(imol, imol_map)
def ok_to_do_density_correlations_qm():
if poor_density_checkbutton:
return poor_density_checkbutton.get_active()
else:
return True
def ok_to_have_missing_sidechain_buttons_qm():
if missing_sidechains_checkbutton:
return missing_sidechains_checkbutton.get_active()
else:
return True
def ok_to_do_CG_torsion_diffs_qm():
try:
CG_spin_search
except:
return False
return cg_torsion_diff_checkbutton.get_active()
def go_to_atom_in_molecule(imol, atom_spec):
coot.set_go_to_atom_molecule(imol)
rdf.set_go_to_atom_from_atom_spec(atom_spec)
def go_to_residue_in_molecule(imol, res_spec):
coot.set_go_to_atom_molecule(imol)
rdf.set_go_to_atom_from_res_spec(res_spec)
def generator(res_spec):
func = lambda res_spec_c=res_spec : go_to_residue_in_molecule(imol, res_spec_c)
def action(arg):
func(res_spec)
return action
def generator_for_atom_spec(atom_spec):
func = lambda atom_spec_c=atom_spec : go_to_atom_in_molecule(imol, atom_spec_c)
def action(arg):
func(atom_spec)
return action
def make_buttons():
frb = find_rama_baddies()
fcbb = find_c_beta_baddies()
filtered_mao_baddies = filter_molecule_atom_overlap_baddies(molecule_atom_overlap_baddies())
residue_correlations = [] if not ok_to_do_density_correlations_qm() \
else coot.map_to_model_correlation_per_residue_py(imol,
coot_utils.all_residues_sans_water(imol),
0,
imol_map)
def get_rama_prob(val):
return val[1]
# rama
baddies = filter(lambda baddie: baddie[1] < 0.002, frb[1])
# baddies.sort(key=get_rama_prob)
sorted_filtered_rama_baddies = baddies
# c-beta
c_beta_baddies = filter(lambda baddie: baddie[1][0][1] > 0.25, fcbb)
def get_c_beta_score(val):
return val[1][0][1]
# c_beta_baddies.sort(key=get_c_beta_score, reverse=True)
sorted_filtered_c_beta_baddies = c_beta_baddies
# Density correlations
#
density_baddies = filter(lambda baddie: baddie[1] < 0.8, residue_correlations)
# CG Torsion
#
cg_torsion_baddies = find_em_ringer_baddies()
# Rotamers
#
rotamer_baddies = rotamer_score_residues(imol)
filtered_rotamer_baddies = filter_rotamer_baddies(rotamer_baddies)
def get_rotamer_score(val):
if val[1] == 0.0:
# score things with score 0.0 (meaning missing sidechain)
# as if they are better than low probability outliers
# give high score in sorting
return 10
else:
return val[1]
sorted_filtered_rotamer_baddies = filtered_rotamer_baddies.sort(key=get_rotamer_score)
rama_buttons = []
for baddie in sorted_filtered_rama_baddies:
spec, rama_prob = baddie
score_string = '{:6.2f} %'.format(100 * rama_prob)
button_label = "Ramachandran Outlier " + \
res_spec_utils.residue_spec_to_chain_id(spec) + \
" " + \
str(coot_utils.residue_spec_to_res_no(spec)) + \
coot_utils.residue_spec_to_ins_code(spec) + \
" " + \
coot_utils.residue_spec_to_residue_name(imol, spec) + \
" " + \
score_string
rama_buttons.append([button_label, generator(spec)])
c_beta_buttons = []
for baddie in sorted_filtered_c_beta_baddies:
spec = baddie[0]
score = baddie[1][0][1] # only the first score
score_string = '{:6.2f}'.format(score)
button_label = "C-beta deviant " + \
residue_spec_to_string(spec) + \
" " + \
coot_utils.residue_spec_to_residue_name(imol, spec) + \
" " + \
score_string + u'\u212B'.encode('utf-8')
c_beta_buttons.append([button_label, generator(residue_spec)])
non_pro_cis_peptide_buttons = []
for baddie in non_pro_cis_peptide_baddies():
spec_1 = baddie[0]
spec_2 = baddie[1]
omega = baddie[2]
button_label = "Non-PRO cis-peptide " + \
residue_spec_to_string(spec_1) + \
" - " + \
residue_spec_to_string(spec_2)
non_pro_cis_peptide_buttons.append([button_label, generator(spec_1)])
twisted_trans_peptide_buttons = []
for baddie in twisted_trans_peptide_baddies():
spec_1 = baddie[0]
spec_2 = baddie[1]
omega = baddie[2]
button_label = "Twisted trans-peptide " + \
residue_spec_to_string(spec_1) + \
" - " + \
residue_spec_to_string(spec_2)
twisted_trans_peptide_buttons.append([button_label, generator(spec_1)])
rota_buttons = []
for baddie in filtered_rotamer_baddies:
spec, score = baddie
# Paul is not sure that he likes a score of
# 0.0 meaning "Missing sidechain"
# we have lost some information on the way.
# 20200511-PE Yeah, like the fact that the residue was RNA!
#
score_string = '{:6.2f} %'.format(score)
ms_string = "Missing Sidechain" if score == 0.0 else "Rotamer Outlier"
rot_name = coot.get_rotamer_name_py(imol,
res_spec_utils.residue_spec_to_chain_id(spec),
res_spec_utils.residue_spec_to_res_no(spec),
coot_utils.residue_spec_to_ins_code(spec))
button_label = ms_string + " " + \
residue_spec_to_string(spec) + \
" " + \
coot_utils.residue_spec_to_residue_name(imol, spec) + \
" "
button_label += rot_name if isinstance(rot_name, str) else " "
button_label += "" if score == 0.0 else score_string
rota_buttons.append([button_label, generator(spec)])
density_baddies_buttons = []
for baddie in density_baddies:
spec, score = baddie
button_label = "Poor Density Fit " + \
residue_spec_to_string(spec) + \
" " + \
'{:5.2f}'.format(score)
density_baddies_buttons.append([button_label, generator(spec)])
cg_torsion_buttons = []
for baddie in cg_torsion_baddies:
spec, score = baddie
button_label = "CG Torsion Diff " + \
residue_spec_to_string(spec) + \
" " + \
'{:5.2f}'.format(score)
cg_torsion_buttons.append([button_label, generator(spec)])
chiral_volume_buttons = []
for baddie_atom_spec in find_chiral_volume_baddies():
atom_spec = baddie_atom_spec
if len(atom_spec) == 6:
atom_spec = atom_spec[1:]
button_label = "Chiral Volume Error " + coot_utils.atom_spec_to_string(atom_spec)
func = generator_for_atom_spec(atom_spec)
chiral_volume_buttons.append([button_label, func])
atom_overlap_buttons = []
for baddie in filtered_mao_baddies:
atom_spec_1 = baddie['atom-1-spec']
atom_spec_2 = baddie['atom-2-spec']
overlap = baddie['overlap-volume']
button_label = "Atom Overlap " + \
coot_utils.atom_spec_to_string(atom_spec_1) + \
" on " + \
coot_utils.atom_spec_to_string(atom_spec_2) + \
" OV: " + \
'{:5.2f}'.format(overlap)
atom_overlap_buttons.append([button_label, generator_for_atom_spec(atom_spec_1)])
buttons = chiral_volume_buttons + \
rama_buttons + \
rota_buttons + \
non_pro_cis_peptide_buttons + \
twisted_trans_peptide_buttons + \
density_baddies_buttons + \
c_beta_buttons + \
cg_torsion_buttons + \
atom_overlap_buttons
return buttons
# main line
buttons = make_buttons()
dialog_vbox, window = coot_gui.dialog_box_of_buttons(make_window_title(len(buttons)),
[350, 400], buttons, " Close ")
window_bits = window.get_children()
vbox_outer = window_bits[0]
control_button_vbox_1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
missing_sidechains_checkbutton_local = Gtk.CheckButton("Missing Sidechains")
poor_density_checkbutton_local = Gtk.CheckButton("Poor Density Fit")
cg_torsion_diff_checkbutton_local = Gtk.CheckButton("CG Torsion Diff.")
regenerate_button_local = Gtk.Button("Update")
missing_sidechains_checkbutton = missing_sidechains_checkbutton_local
poor_density_checkbutton = poor_density_checkbutton_local
cg_torsion_diff_checkbutton = cg_torsion_diff_checkbutton_local
missing_sidechains_checkbutton.set_active(True)
poor_density_checkbutton.set_active(True)
cg_torsion_diff_checkbutton.set_active(True)
control_button_vbox_1.append(missing_sidechains_checkbutton)
control_button_vbox_1.append(poor_density_checkbutton)
vbox_outer.append(regenerate_button_local)
vbox_outer.append(control_button_vbox_1)
regenerate_button_local.connect("clicked", regenerate_button_fn)
def missing_sidechains_checkbutton_toggled(widget):
state = widget.get_active()
if not state:
# i.e. no buttons with "Missing Sidechain"
# Mmmh, really?!?
destroy_buttons_with_label("Missing Sidechain", dialog_vbox)
missing_sidechains_checkbutton.connect("toggled",
missing_sidechains_checkbutton_toggled)
def poor_density_checkbutton_toggled(widget):
state = widget.get_active()
if not state:
destroy_buttons_with_label("Poor Density", dialog_vbox)
poor_density_checkbutton.connect("toggled",
poor_density_checkbutton_toggled)
# 20190102-PE depends on the version of coot that we are using
#
have_cg_spin = False
try:
CG_spin_search
have_cg_spin = True
except:
pass
if have_cg_spin:
control_button_vbox_1.append(cg_torsion_diff_checkbutton)
cg_torsion_diff_checkbutton.show()
def cg_torsion_diff_checkbutton_toggled(widget):
state = widget.get_active()
if not state:
destroy_buttons_with_label("CG TOrsion", dialog_vbox)
cg_torsion_diff_checkbutton.connect("toggled",
cg_torsion_diff_checkbutton_toggled)
control_button_vbox_1.show()
missing_sidechains_checkbutton.show()
poor_density_checkbutton.show()
regenerate_button_local.show()
|