From b4c8eba3a4e71347fdc2a71897bddd80b03e7daa Mon Sep 17 00:00:00 2001 From: Jenke Scheen Date: Wed, 10 Apr 2024 11:02:53 +0200 Subject: [PATCH] color backbone contacts green --- choppa/render/test_sess.pse | Bin 412429 -> 414677 bytes choppa/render/utils.py | 184 ++++++------------------------------ 2 files changed, 28 insertions(+), 156 deletions(-) diff --git a/choppa/render/test_sess.pse b/choppa/render/test_sess.pse index 7f3caf38466191a85ee7e9e9e85d31be0af97344..b63614c24c27934e52b3e3dd94934bc440008367 100644 GIT binary patch delta 43349 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 diff --git a/choppa/render/utils.py b/choppa/render/utils.py index 3901e7b..6560e5d 100644 --- a/choppa/render/utils.py +++ b/choppa/render/utils.py @@ -25,13 +25,11 @@ def show_contacts( selection_residues, selection_lig, contact_color, - cutoff=3.6, bigcutoff=4.0, ): """ - PyMOL plugin that provides show_contacts command and GUI for highlighting good and bad - polar contacts. Factored out of clustermols by Matthew Baumgartner. The advantage of this - package is it requires many fewer dependencies. + Heavily reduced PyMOL plugin that provides show_contacts command and GUI for highlighting good and bad + polar contacts. Factored out of clustermols by Matthew Baumgartner. Returns: List of contacts @@ -41,160 +39,34 @@ def show_contacts( # ensure only N and O atoms are in the selection all_don_acc_lig = selection_lig + " and (donor or acceptor)" - all_don_acc_res = selection_residues + " and (donor or acceptor)" + all_don_acc_res = selection_residues + " and (donor or acceptor) and sidechain" + all_don_acc_res_backbone = selection_residues + " and (donor or acceptor) and backbone" # if theses selections turn out not to have any atoms in them, pymol throws cryptic errors when calling the dist function like: # 'Selector-Error: Invalid selection name' - # So for each one, manually perform the selection and then pass the reference to the distance command and at the end, clean up the selections - # the return values are the count of the number of atoms - all1_sele_count = pymol_instance.cmd.select("all_don_acc1_sele", all_don_acc_lig) - all2_sele_count = pymol_instance.cmd.select("all_don_acc2_sele", all_don_acc_res) - - ######################################## - contacts_name = f"{selection_residues}_contacts" - if all1_sele_count and all2_sele_count: - pymol_instance.cmd.distance( - contacts_name, "all_don_acc1_sele", "all_don_acc2_sele", bigcutoff, mode=0 - ) - pymol_instance.cmd.set("dash_radius", "0.09", contacts_name) - pymol_instance.cmd.set("dash_color", contact_color, contacts_name) - pymol_instance.cmd.hide("labels", contacts_name) - - - - - - # ######################################## - # # compute good polar interactions according to pymol - # polres = result + "_polar" - # if all1_sele_count and all2_sele_count: - # pymol_instance.cmd.distance( - # polres, "all_don_acc1_sele", "all_don_acc2_sele", cutoff, mode=2 - # ) # hopefully this checks angles? Yes - # pymol_instance.cmd.set("dash_radius", "0.126", polres) - - # ######################################## - # # When running distance in mode=2, the cutoff parameter is ignored if set higher then the default of 3.6 - # # so set it to the passed in cutoff and change it back when you are done. - # old_h_bond_cutoff_center = pymol_instance.cmd.get( - # "h_bond_cutoff_center" - # ) # ideal geometry - # old_h_bond_cutoff_edge = pymol_instance.cmd.get( - # "h_bond_cutoff_edge" - # ) # minimally acceptable geometry - # pymol_instance.cmd.set("h_bond_cutoff_center", bigcutoff) - # pymol_instance.cmd.set("h_bond_cutoff_edge", bigcutoff) - - # # compute possibly suboptimal polar interactions using the user specified distance - # pol_ok_res = result + "_polar_ok" - # if all1_sele_count and all2_sele_count: - # pymol_instance.cmd.distance( - # pol_ok_res, "all_don_acc1_sele", "all_don_acc2_sele", bigcutoff, mode=2 - # ) - # pymol_instance.cmd.set("dash_radius", "0.06", pol_ok_res) - - # # now reset the h_bond cutoffs - # pymol_instance.cmd.set("h_bond_cutoff_center", old_h_bond_cutoff_center) - # pymol_instance.cmd.set("h_bond_cutoff_edge", old_h_bond_cutoff_edge) - - # ######################################## - - # onlyacceptors1 = selection + " and (acceptor and !donor)" - # onlyacceptors2 = selection2 + " and (acceptor and !donor)" - # onlydonors1 = selection + " and (!acceptor and donor)" - # onlydonors2 = selection2 + " and (!acceptor and donor)" - - # # perform the selections - # onlyacceptors1_sele_count = pymol_instance.cmd.select( - # "onlyacceptors1_sele", onlyacceptors1 - # ) - # onlyacceptors2_sele_count = pymol_instance.cmd.select( - # "onlyacceptors2_sele", onlyacceptors2 - # ) - # onlydonors1_sele_count = pymol_instance.cmd.select("onlydonors1_sele", onlydonors1) - # onlydonors2_sele_count = pymol_instance.cmd.select("onlydonors2_sele", onlydonors2) - - # # print out some warnings - # if SC_DEBUG > 2: - # if not onlyacceptors1_sele_count: - # print("Warning: onlyacceptors1 selection empty!") - # if not onlyacceptors2_sele_count: - # print("Warning: onlyacceptors2 selection empty!") - # if not onlydonors1_sele_count: - # print("Warning: onlydonors1 selection empty!") - # if not onlydonors2_sele_count: - # print("Warning: onlydonors2 selection empty!") - - # accres = result + "_aa" - # if onlyacceptors1_sele_count and onlyacceptors2_sele_count: - # aa_dist_out = pymol_instance.cmd.distance( - # accres, "onlyacceptors1_sele", "onlyacceptors2_sele", cutoff, 0 - # ) - - # if aa_dist_out < 0: - # print( - # "\n\nCaught a pymol selection error in acceptor-acceptor selection of show_contacts" - # ) - # print("accres:", accres) - # print("onlyacceptors1", onlyacceptors1) - # print("onlyacceptors2", onlyacceptors2) - # return False - - # pymol_instance.cmd.set("dash_color", "red", accres) - # pymol_instance.cmd.set("dash_radius", "0.125", accres) - - # ######################################## - - # donres = result + "_dd" - # if onlydonors1_sele_count and onlydonors2_sele_count: - # dd_dist_out = pymol_instance.cmd.distance( - # donres, "onlydonors1_sele", "onlydonors2_sele", cutoff, 0 - # ) - - # # try to catch the error state - # if dd_dist_out < 0: - # print("\n\nCaught a pymol selection error in dd selection of show_contacts") - # print("donres:", donres) - # print("onlydonors1", onlydonors1) - # print("onlydonors2", onlydonors2) - # print( - # "pymol_instance.cmd.distance('" - # + donres - # + "', '" - # + onlydonors1 - # + "', '" - # + onlydonors2 - # + "', " - # + str(cutoff) - # + ", 0)" - # ) - # return False - - # pymol_instance.cmd.set("dash_color", "red", donres) - # pymol_instance.cmd.set("dash_radius", "0.125", donres) - - # ################################################## - # # find the buried unpaired atoms of the receptor # - # ################################################## - - # # initialize the variable for when CALC_SASA is False - # unpaired_atoms = "" - - # # Group - # pymol_instance.cmd.group( - # result, - # "%s %s %s %s %s %s" - # % (polres, allres, accres, donres, pol_ok_res, unpaired_atoms), - # ) - - # # Clean up the selection objects - # # if the show_contacts debug level is high enough, don't delete them. - # if SC_DEBUG < 5: - # pymol_instance.cmd.delete("all_don_acc1_sele") - # pymol_instance.cmd.delete("all_don_acc2_sele") - # pymol_instance.cmd.delete("onlyacceptors1_sele") - # pymol_instance.cmd.delete("onlyacceptors2_sele") - # pymol_instance.cmd.delete("onlydonors1_sele") - # pymol_instance.cmd.delete("onlydonors2_sele") + all_lig_sele_count = pymol_instance.cmd.select("all_don_acc_lig_sele", all_don_acc_lig) + all_res_sele_count = pymol_instance.cmd.select("all_don_acc_res_sele", all_don_acc_res) + _ = pymol_instance.cmd.select("all_don_acc_res_bb_sele", all_don_acc_res_backbone) # not sure if we need to check for this backbone one? + if not all_lig_sele_count and all_res_sele_count: + return False + + # now make the actual contacts + # first with sidechains, color as requested + contacts_name = f"{selection_residues}_contacts_sc" + pymol_instance.cmd.distance( + contacts_name, "all_don_acc_lig_sele", "all_don_acc_res_sele", bigcutoff, mode=0 + ) + pymol_instance.cmd.set("dash_radius", "0.09", contacts_name) + pymol_instance.cmd.set("dash_color", contact_color, contacts_name) + pymol_instance.cmd.hide("labels", contacts_name) + + # now contacts with backbone, color these green + contacts_name = f"{selection_residues}_contacts_bb" + pymol_instance.cmd.distance( + contacts_name, "all_don_acc_lig_sele", "all_don_acc_res_bb_sele", bigcutoff, mode=0 + ) + pymol_instance.cmd.set("dash_radius", "0.09", contacts_name) + pymol_instance.cmd.set("dash_color", "green", contacts_name) + pymol_instance.cmd.hide("labels", contacts_name) return True \ No newline at end of file