Difference between revisions of "Show contacts"

From PyMOLWiki
Jump to navigation Jump to search
(remove code in favor of github link)
Tag: Replaced
 
Line 1: Line 1:
 
{{Infobox script-repo
 
{{Infobox script-repo
|type      = script
+
|type      = plugin
|download = [https://github.com/Pymol-Scripts/Pymol-script-repo/blob/master/plugins/show_contacts.py]
+
|filename = plugins/show_contacts.py
 
|author    = [[User:DavidKoes|David Ryan Koes]]
 
|author    = [[User:DavidKoes|David Ryan Koes]]
 
|license  = [http://creativecommons.org/licenses/by/4.0/ CC BY 4.0]
 
|license  = [http://creativecommons.org/licenses/by/4.0/ CC BY 4.0]
Line 22: Line 22:
 
* '''cutoff''' = cutoff for good contacts (yellow dashes)
 
* '''cutoff''' = cutoff for good contacts (yellow dashes)
 
* '''bigcutoff''' = cutoff for suboptimal contacts (purple dashes)
 
* '''bigcutoff''' = cutoff for suboptimal contacts (purple dashes)
 
 
 
 
== The Code ==
 
 
Copy the following text and save it as show_contacts.py
 
 
<source lang="python">
 
#!/usr/bin/python
 
 
'''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.
 
'''
 
from __future__ import print_function
 
 
import sys,os
 
 
import Pmw
 
from pymol import cmd
 
 
DEBUG=1
 
 
def show_contacts(selection,selection2,result="contacts",cutoff=3.6, bigcutoff = 4.0, SC_DEBUG = DEBUG):
 
    """
 
    USAGE
 
   
 
    show_contacts selection, selection2, [result=contacts],[cutoff=3.6],[bigcutoff=4.0]
 
   
 
    Show various polar contacts, the good, the bad, and the ugly.
 
   
 
    Edit MPB 6-26-14: The distances are heavy atom distances, so I upped the default cutoff to 4.0
 
   
 
    Returns:
 
    True/False -  if False, something went wrong
 
    """
 
    if SC_DEBUG > 4:
 
        print('Starting show_contacts')
 
        print('selection = "' + selection + '"')
 
        print('selection2 = "' + selection2 + '"')
 
           
 
 
    #if the group of contacts already exist, delete them
 
    cmd.delete(result)
 
 
    # ensure only N and O atoms are in the selection
 
    all_don_acc1 = selection + " and (donor or acceptor)"
 
    all_don_acc2 = selection2 + " and  (donor or acceptor)"
 
   
 
    if SC_DEBUG > 4:
 
        print('all_don_acc1 = "' + all_don_acc1 + '"')
 
        print('all_don_acc2 = "' + all_don_acc2 + '"')
 
   
 
    #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 = cmd.select('all_don_acc1_sele', all_don_acc1)
 
    all2_sele_count = cmd.select('all_don_acc2_sele', all_don_acc2)
 
   
 
    #print out some warnings
 
    if DEBUG > 3:
 
        if not all1_sele_count:
 
            print('Warning: all_don_acc1 selection empty!')
 
        if not all2_sele_count:
 
            print('Warning: all_don_acc2 selection empty!')
 
   
 
    ########################################
 
    allres = result + "_all"
 
    if all1_sele_count and all2_sele_count:
 
        cmd.distance(allres, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 0)
 
        cmd.set("dash_radius", "0.05", allres)
 
        cmd.set("dash_color", "purple", allres)
 
        cmd.hide("labels", allres)
 
   
 
    ########################################
 
    #compute good polar interactions according to pymol
 
    polres = result + "_polar"
 
    if all1_sele_count and all2_sele_count:
 
        cmd.distance(polres, 'all_don_acc1_sele', 'all_don_acc2_sele', cutoff, mode = 2) #hopefully this checks angles? Yes
 
        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 = cmd.get('h_bond_cutoff_center') # ideal geometry
 
    old_h_bond_cutoff_edge = cmd.get('h_bond_cutoff_edge') # minimally acceptable geometry
 
    cmd.set('h_bond_cutoff_center', bigcutoff)
 
    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:
 
        cmd.distance(pol_ok_res, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 2)
 
        cmd.set("dash_radius", "0.06", pol_ok_res)
 
 
    #now reset the h_bond cutoffs
 
    cmd.set('h_bond_cutoff_center', old_h_bond_cutoff_center)
 
    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 = cmd.select('onlyacceptors1_sele', onlyacceptors1)
 
    onlyacceptors2_sele_count = cmd.select('onlyacceptors2_sele', onlyacceptors2)
 
    onlydonors1_sele_count = cmd.select('onlydonors1_sele', onlydonors1)
 
    onlydonors2_sele_count = 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 = 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
 
   
 
        cmd.set("dash_color","red",accres)
 
        cmd.set("dash_radius","0.125",accres)
 
   
 
    ########################################
 
   
 
    donres = result+"_dd"
 
    if onlydonors1_sele_count and onlydonors2_sele_count:
 
        dd_dist_out = 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("cmd.distance('" + donres + "', '" + onlydonors1 + "', '" + onlydonors2 + "', " + str(cutoff) + ", 0)") 
 
            return False
 
       
 
        cmd.set("dash_color","red",donres) 
 
        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
 
    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:
 
        cmd.delete('all_don_acc1_sele')
 
        cmd.delete('all_don_acc2_sele')
 
        cmd.delete('onlyacceptors1_sele')
 
        cmd.delete('onlyacceptors2_sele')
 
        cmd.delete('onlydonors1_sele')
 
        cmd.delete('onlydonors2_sele')
 
   
 
   
 
    return True
 
cmd.extend('contacts', show_contacts) #contacts to avoid clashing with cluster_mols version
 
 
 
 
   
 
   
 
#################################################################################
 
########################### Start of pymol plugin code ##########################
 
#################################################################################
 
 
 
about_text = '''show_contacts was factored out of the much more full-featured cluster_mols
 
by Dr. Matt Baumgartner (https://pymolwiki.org/index.php/Cluster_mols).  It provides
 
an easy way to highlight polar contacts (and clashes) between two selections without
 
requiring the installation of additional dependencies.
 
'''
 
 
class Show_Contacts:
 
    ''' Main Pymol Plugin Class '''
 
    def __init__(self, app):
 
        parent = app.root
 
        self.parent = parent
 
       
 
        self.app = app
 
       
 
 
        ############################################################################################
 
        ### Open a window with options to select to loaded objects ###
 
        ############################################################################################
 
 
        self.select_dialog = Pmw.Dialog(parent,
 
                        buttons = ('Ok','Cancel'),
 
                        title = 'Show Contacts Plugin',
 
                        command = self.button_pressed )
 
   
 
        self.select_dialog.withdraw()
 
   
 
 
        #allow the user to select from objects already loaded in pymol
 
        self.select_object_combo_box = Pmw.ComboBox(self.select_dialog.interior(),
 
                                                              scrolledlist_items=[],
 
                                                              labelpos='w',
 
                                                              label_text='Select loaded object:',
 
                                                              listbox_height = 2,
 
                                                              dropdown=True)
 
        self.select_object_combo_box2 = Pmw.ComboBox(self.select_dialog.interior(),
 
                                                              scrolledlist_items=[],
 
                                                              labelpos='w',
 
                                                              label_text='Select loaded object:',
 
                                                              listbox_height = 2,
 
                                                              dropdown=True)                                                             
 
        self.select_object_combo_box.grid(column=1, row=0)
 
        self.select_object_combo_box2.grid(column=2, row=0)
 
        self.populate_ligand_select_list()
 
        self.select_dialog.show()
 
       
 
 
     
 
    def button_pressed(self, result):
 
        if hasattr(result,'keycode'):
 
            if result.keycode == 36:
 
                print('keycode:', result.keycode)
 
        elif result == 'Ok' or result == 'Exit' or result == None:
 
            s1 = self.select_object_combo_box.get()
 
            s2 = self.select_object_combo_box2.get()
 
            show_contacts(s1,s2,'%s_%s'%(s1,s2))
 
            self.select_dialog.withdraw()           
 
        elif result == 'Cancel' or result == None:
 
            self.select_dialog.withdraw()
 
 
           
 
 
   
 
    def populate_ligand_select_list(self):
 
        ''' Go thourgh the loaded objects in PyMOL and add them to the selected list. '''
 
        #get the loaded objects
 
        loaded_objects = [ name for name in cmd.get_names('all') if '_cluster_' not in name ]
 
       
 
        self.select_object_combo_box.clear()
 
        self.select_object_combo_box2.clear()
 
       
 
        for ob in loaded_objects:
 
            self.select_object_combo_box.insert('end', ob)
 
            self.select_object_combo_box2.insert('end', ob)
 
       
 
 
 
   
 
def __init__(self):
 
    self.menuBar.addmenuitem('Plugin', 'command', 'Show Contacts', label = 'Show Contacts', command = lambda s=self : Show_Contacts(s)) 
 
       
 
 
</source>
 
  
  

Latest revision as of 03:05, 4 April 2020

Type PyMOL Plugin
Download plugins/show_contacts.py
Author(s) David Ryan Koes
License CC BY 4.0
This code has been put under version control in the project Pymol-script-repo

Introduction

PyMOL Plugin for displaying polar contacts. Good hydrogen bonds (as determined by PyMOL) are shown in yellow. Electrostatic clashes (donor-donor or acceptor-acceptor) are shown in red. Close (<4.0 A) but not ideal contacts are shown in purple. Cutoffs are configurable. Exports the command `contacts` which takes two selections and an optional name for the generated contacts group. Alternatively, the selections can be chosen using a dialog box accessible from the Plugins menu.


Usage

show_contacts sel1, sel2, result="contacts", cutoff=3.6, bigcutoff=4.0

Required Arguments

  • sel1 = first selection
  • sel2 = second selection


Optional Arguments

  • result = name of created group containing contacts
  • cutoff = cutoff for good contacts (yellow dashes)
  • bigcutoff = cutoff for suboptimal contacts (purple dashes)