<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Show_contacts</id>
	<title>Show contacts - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Show_contacts"/>
	<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Show_contacts&amp;action=history"/>
	<updated>2026-06-26T05:56:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Show_contacts&amp;diff=14588&amp;oldid=prev</id>
		<title>Cchem: 2 revisions</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Show_contacts&amp;diff=14588&amp;oldid=prev"/>
		<updated>2019-04-01T03:11:58Z</updated>

		<summary type="html">&lt;p&gt;2 revisions&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Infobox script-repo&lt;br /&gt;
|type      = script&lt;br /&gt;
|download  = [https://github.com/Pymol-Scripts/Pymol-script-repo/blob/master/plugins/show_contacts.py]&lt;br /&gt;
|author    = [[User:DavidKoes|David Ryan Koes]]&lt;br /&gt;
|license   = [http://creativecommons.org/licenses/by/4.0/ CC BY 4.0]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
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 (&amp;lt;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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
 show_contacts sel1, sel2, result=&amp;quot;contacts&amp;quot;, cutoff=3.6, bigcutoff=4.0&lt;br /&gt;
&lt;br /&gt;
== Required Arguments ==&lt;br /&gt;
* '''sel1''' = first selection&lt;br /&gt;
* '''sel2''' = second selection&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Optional Arguments ==&lt;br /&gt;
* '''result''' = name of created group containing contacts&lt;br /&gt;
* '''cutoff''' = cutoff for good contacts (yellow dashes)&lt;br /&gt;
* '''bigcutoff''' = cutoff for suboptimal contacts (purple dashes)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Code ==&lt;br /&gt;
&lt;br /&gt;
Copy the following text and save it as show_contacts.py &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
'''PyMOL plugin that provides show_contacts command and GUI &lt;br /&gt;
for highlighting good and bad polar contacts. Factored out of &lt;br /&gt;
clustermols by Matthew Baumgartner.&lt;br /&gt;
The advantage of this package is it requires many fewer dependencies.&lt;br /&gt;
'''&lt;br /&gt;
from __future__ import print_function&lt;br /&gt;
&lt;br /&gt;
import sys,os&lt;br /&gt;
&lt;br /&gt;
import Pmw&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
&lt;br /&gt;
DEBUG=1&lt;br /&gt;
&lt;br /&gt;
def show_contacts(selection,selection2,result=&amp;quot;contacts&amp;quot;,cutoff=3.6, bigcutoff = 4.0, SC_DEBUG = DEBUG):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    USAGE&lt;br /&gt;
    &lt;br /&gt;
    show_contacts selection, selection2, [result=contacts],[cutoff=3.6],[bigcutoff=4.0]&lt;br /&gt;
    &lt;br /&gt;
    Show various polar contacts, the good, the bad, and the ugly.&lt;br /&gt;
    &lt;br /&gt;
    Edit MPB 6-26-14: The distances are heavy atom distances, so I upped the default cutoff to 4.0&lt;br /&gt;
    &lt;br /&gt;
    Returns:&lt;br /&gt;
    True/False -  if False, something went wrong&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if SC_DEBUG &amp;gt; 4:&lt;br /&gt;
        print('Starting show_contacts')&lt;br /&gt;
        print('selection = &amp;quot;' + selection + '&amp;quot;')&lt;br /&gt;
        print('selection2 = &amp;quot;' + selection2 + '&amp;quot;')&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
    #if the group of contacts already exist, delete them&lt;br /&gt;
    cmd.delete(result)&lt;br /&gt;
&lt;br /&gt;
    # ensure only N and O atoms are in the selection&lt;br /&gt;
    all_don_acc1 = selection + &amp;quot; and (donor or acceptor)&amp;quot;&lt;br /&gt;
    all_don_acc2 = selection2 + &amp;quot; and  (donor or acceptor)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    if SC_DEBUG &amp;gt; 4:&lt;br /&gt;
        print('all_don_acc1 = &amp;quot;' + all_don_acc1 + '&amp;quot;')&lt;br /&gt;
        print('all_don_acc2 = &amp;quot;' + all_don_acc2 + '&amp;quot;')&lt;br /&gt;
    &lt;br /&gt;
    #if theses selections turn out not to have any atoms in them, pymol throws cryptic errors when calling the dist function like:&lt;br /&gt;
    #'Selector-Error: Invalid selection name'&lt;br /&gt;
    #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&lt;br /&gt;
    #the return values are the count of the number of atoms&lt;br /&gt;
    all1_sele_count = cmd.select('all_don_acc1_sele', all_don_acc1)&lt;br /&gt;
    all2_sele_count = cmd.select('all_don_acc2_sele', all_don_acc2)&lt;br /&gt;
    &lt;br /&gt;
    #print out some warnings&lt;br /&gt;
    if DEBUG &amp;gt; 3:&lt;br /&gt;
        if not all1_sele_count:&lt;br /&gt;
            print('Warning: all_don_acc1 selection empty!')&lt;br /&gt;
        if not all2_sele_count:&lt;br /&gt;
            print('Warning: all_don_acc2 selection empty!')&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    allres = result + &amp;quot;_all&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(allres, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 0)&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;, &amp;quot;0.05&amp;quot;, allres)&lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;, &amp;quot;purple&amp;quot;, allres)&lt;br /&gt;
        cmd.hide(&amp;quot;labels&amp;quot;, allres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    #compute good polar interactions according to pymol&lt;br /&gt;
    polres = result + &amp;quot;_polar&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(polres, 'all_don_acc1_sele', 'all_don_acc2_sele', cutoff, mode = 2) #hopefully this checks angles? Yes&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.126&amp;quot;,polres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    #When running distance in mode=2, the cutoff parameter is ignored if set higher then the default of 3.6&lt;br /&gt;
    #so set it to the passed in cutoff and change it back when you are done.&lt;br /&gt;
    old_h_bond_cutoff_center = cmd.get('h_bond_cutoff_center') # ideal geometry&lt;br /&gt;
    old_h_bond_cutoff_edge = cmd.get('h_bond_cutoff_edge') # minimally acceptable geometry&lt;br /&gt;
    cmd.set('h_bond_cutoff_center', bigcutoff)&lt;br /&gt;
    cmd.set('h_bond_cutoff_edge', bigcutoff)&lt;br /&gt;
        &lt;br /&gt;
    #compute possibly suboptimal polar interactions using the user specified distance&lt;br /&gt;
    pol_ok_res = result + &amp;quot;_polar_ok&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(pol_ok_res, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 2) &lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;, &amp;quot;0.06&amp;quot;, pol_ok_res)&lt;br /&gt;
&lt;br /&gt;
    #now reset the h_bond cutoffs&lt;br /&gt;
    cmd.set('h_bond_cutoff_center', old_h_bond_cutoff_center)&lt;br /&gt;
    cmd.set('h_bond_cutoff_edge', old_h_bond_cutoff_edge) &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    &lt;br /&gt;
    onlyacceptors1 = selection + &amp;quot; and (acceptor and !donor)&amp;quot;&lt;br /&gt;
    onlyacceptors2 = selection2 + &amp;quot; and (acceptor and !donor)&amp;quot;&lt;br /&gt;
    onlydonors1 = selection + &amp;quot; and (!acceptor and donor)&amp;quot;&lt;br /&gt;
    onlydonors2 = selection2 + &amp;quot; and (!acceptor and donor)&amp;quot;  &lt;br /&gt;
    &lt;br /&gt;
    #perform the selections&lt;br /&gt;
    onlyacceptors1_sele_count = cmd.select('onlyacceptors1_sele', onlyacceptors1)&lt;br /&gt;
    onlyacceptors2_sele_count = cmd.select('onlyacceptors2_sele', onlyacceptors2)&lt;br /&gt;
    onlydonors1_sele_count = cmd.select('onlydonors1_sele', onlydonors1)&lt;br /&gt;
    onlydonors2_sele_count = cmd.select('onlydonors2_sele', onlydonors2)    &lt;br /&gt;
    &lt;br /&gt;
    #print out some warnings&lt;br /&gt;
    if SC_DEBUG &amp;gt; 2:&lt;br /&gt;
        if not onlyacceptors1_sele_count:&lt;br /&gt;
            print('Warning: onlyacceptors1 selection empty!')&lt;br /&gt;
        if not onlyacceptors2_sele_count:&lt;br /&gt;
            print('Warning: onlyacceptors2 selection empty!')&lt;br /&gt;
        if not onlydonors1_sele_count:&lt;br /&gt;
            print('Warning: onlydonors1 selection empty!')&lt;br /&gt;
        if not onlydonors2_sele_count:&lt;br /&gt;
            print('Warning: onlydonors2 selection empty!')    &lt;br /&gt;
            &lt;br /&gt;
    &lt;br /&gt;
    accres = result+&amp;quot;_aa&amp;quot;&lt;br /&gt;
    if onlyacceptors1_sele_count and onlyacceptors2_sele_count:&lt;br /&gt;
        aa_dist_out = cmd.distance(accres, 'onlyacceptors1_sele', 'onlyacceptors2_sele', cutoff, 0)&lt;br /&gt;
&lt;br /&gt;
        if aa_dist_out &amp;lt; 0:&lt;br /&gt;
            print('\n\nCaught a pymol selection error in acceptor-acceptor selection of show_contacts')&lt;br /&gt;
            print('accres:', accres)&lt;br /&gt;
            print('onlyacceptors1', onlyacceptors1)&lt;br /&gt;
            print('onlyacceptors2', onlyacceptors2)&lt;br /&gt;
            return False&lt;br /&gt;
    &lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;,&amp;quot;red&amp;quot;,accres)&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.125&amp;quot;,accres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    &lt;br /&gt;
    donres = result+&amp;quot;_dd&amp;quot;&lt;br /&gt;
    if onlydonors1_sele_count and onlydonors2_sele_count:&lt;br /&gt;
        dd_dist_out = cmd.distance(donres, 'onlydonors1_sele', 'onlydonors2_sele', cutoff, 0)&lt;br /&gt;
        &lt;br /&gt;
        #try to catch the error state &lt;br /&gt;
        if dd_dist_out &amp;lt; 0:&lt;br /&gt;
            print('\n\nCaught a pymol selection error in dd selection of show_contacts')&lt;br /&gt;
            print('donres:', donres)&lt;br /&gt;
            print('onlydonors1', onlydonors1)&lt;br /&gt;
            print('onlydonors2', onlydonors2)&lt;br /&gt;
            print(&amp;quot;cmd.distance('&amp;quot; + donres + &amp;quot;', '&amp;quot; + onlydonors1 + &amp;quot;', '&amp;quot; + onlydonors2 + &amp;quot;', &amp;quot; + str(cutoff) + &amp;quot;, 0)&amp;quot;)  &lt;br /&gt;
            return False&lt;br /&gt;
        &lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;,&amp;quot;red&amp;quot;,donres)  &lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.125&amp;quot;,donres)&lt;br /&gt;
    &lt;br /&gt;
    ##########################################################&lt;br /&gt;
    ##### find the buried unpaired atoms of the receptor #####&lt;br /&gt;
    ##########################################################&lt;br /&gt;
    &lt;br /&gt;
    #initialize the variable for when CALC_SASA is False&lt;br /&gt;
    unpaired_atoms = ''&lt;br /&gt;
    &lt;br /&gt;
        &lt;br /&gt;
    ## Group&lt;br /&gt;
    cmd.group(result,&amp;quot;%s %s %s %s %s %s&amp;quot; % (polres, allres, accres, donres, pol_ok_res, unpaired_atoms))&lt;br /&gt;
    &lt;br /&gt;
    ## Clean up the selection objects&lt;br /&gt;
    #if the show_contacts debug level is high enough, don't delete them.&lt;br /&gt;
    if SC_DEBUG &amp;lt; 5:&lt;br /&gt;
        cmd.delete('all_don_acc1_sele')&lt;br /&gt;
        cmd.delete('all_don_acc2_sele')&lt;br /&gt;
        cmd.delete('onlyacceptors1_sele')&lt;br /&gt;
        cmd.delete('onlyacceptors2_sele')&lt;br /&gt;
        cmd.delete('onlydonors1_sele')&lt;br /&gt;
        cmd.delete('onlydonors2_sele')&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    return True&lt;br /&gt;
cmd.extend('contacts', show_contacts) #contacts to avoid clashing with cluster_mols version&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
#################################################################################&lt;br /&gt;
########################### Start of pymol plugin code ##########################&lt;br /&gt;
#################################################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
about_text = '''show_contacts was factored out of the much more full-featured cluster_mols&lt;br /&gt;
by Dr. Matt Baumgartner (https://pymolwiki.org/index.php/Cluster_mols).  It provides&lt;br /&gt;
an easy way to highlight polar contacts (and clashes) between two selections without&lt;br /&gt;
requiring the installation of additional dependencies.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
class Show_Contacts:&lt;br /&gt;
    ''' Main Pymol Plugin Class '''&lt;br /&gt;
    def __init__(self, app):&lt;br /&gt;
        parent = app.root&lt;br /&gt;
        self.parent = parent&lt;br /&gt;
        &lt;br /&gt;
        self.app = app&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
        ############################################################################################&lt;br /&gt;
        ### Open a window with options to select to loaded objects ###&lt;br /&gt;
        ############################################################################################&lt;br /&gt;
&lt;br /&gt;
        self.select_dialog = Pmw.Dialog(parent, &lt;br /&gt;
                         buttons = ('Ok','Cancel'), &lt;br /&gt;
                         title = 'Show Contacts Plugin',&lt;br /&gt;
                         command = self.button_pressed )&lt;br /&gt;
    &lt;br /&gt;
        self.select_dialog.withdraw()&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
        #allow the user to select from objects already loaded in pymol&lt;br /&gt;
        self.select_object_combo_box = Pmw.ComboBox(self.select_dialog.interior(),&lt;br /&gt;
                                                               scrolledlist_items=[],&lt;br /&gt;
                                                               labelpos='w',&lt;br /&gt;
                                                               label_text='Select loaded object:',&lt;br /&gt;
                                                               listbox_height = 2,&lt;br /&gt;
                                                               dropdown=True)&lt;br /&gt;
        self.select_object_combo_box2 = Pmw.ComboBox(self.select_dialog.interior(),&lt;br /&gt;
                                                               scrolledlist_items=[],&lt;br /&gt;
                                                               labelpos='w',&lt;br /&gt;
                                                               label_text='Select loaded object:',&lt;br /&gt;
                                                               listbox_height = 2,&lt;br /&gt;
                                                               dropdown=True)                                                               &lt;br /&gt;
        self.select_object_combo_box.grid(column=1, row=0)&lt;br /&gt;
        self.select_object_combo_box2.grid(column=2, row=0)&lt;br /&gt;
        self.populate_ligand_select_list()&lt;br /&gt;
        self.select_dialog.show()&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
      &lt;br /&gt;
    def button_pressed(self, result):&lt;br /&gt;
        if hasattr(result,'keycode'):&lt;br /&gt;
            if result.keycode == 36:&lt;br /&gt;
                print('keycode:', result.keycode)&lt;br /&gt;
        elif result == 'Ok' or result == 'Exit' or result == None:&lt;br /&gt;
            s1 = self.select_object_combo_box.get()&lt;br /&gt;
            s2 = self.select_object_combo_box2.get()&lt;br /&gt;
            show_contacts(s1,s2,'%s_%s'%(s1,s2))&lt;br /&gt;
            self.select_dialog.withdraw()            &lt;br /&gt;
        elif result == 'Cancel' or result == None:&lt;br /&gt;
            self.select_dialog.withdraw()&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
    def populate_ligand_select_list(self):&lt;br /&gt;
        ''' Go thourgh the loaded objects in PyMOL and add them to the selected list. '''&lt;br /&gt;
        #get the loaded objects&lt;br /&gt;
        loaded_objects = [ name for name in cmd.get_names('all') if '_cluster_' not in name ]&lt;br /&gt;
         &lt;br /&gt;
        self.select_object_combo_box.clear()&lt;br /&gt;
        self.select_object_combo_box2.clear()&lt;br /&gt;
        &lt;br /&gt;
        for ob in loaded_objects:&lt;br /&gt;
            self.select_object_combo_box.insert('end', ob)&lt;br /&gt;
            self.select_object_combo_box2.insert('end', ob)&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
def __init__(self):&lt;br /&gt;
    self.menuBar.addmenuitem('Plugin', 'command', 'Show Contacts', label = 'Show Contacts', command = lambda s=self : Show_Contacts(s))  &lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Script_Library]]&lt;br /&gt;
[[Category:Biochemical_Scripts]]&lt;br /&gt;
[[Category:Structural_Biology_Scripts]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Cchem</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Show_contacts&amp;diff=14558&amp;oldid=prev</id>
		<title>Cchem: 2 revisions</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Show_contacts&amp;diff=14558&amp;oldid=prev"/>
		<updated>2019-03-04T03:58:23Z</updated>

		<summary type="html">&lt;p&gt;2 revisions&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Infobox script-repo&lt;br /&gt;
|type      = script&lt;br /&gt;
|download  = [https://github.com/Pymol-Scripts/Pymol-script-repo/blob/master/plugins/show_contacts.py]&lt;br /&gt;
|author    = [[User:DavidKoes|David Ryan Koes]]&lt;br /&gt;
|license   = [http://creativecommons.org/licenses/by/4.0/ CC BY 4.0]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
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 (&amp;lt;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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
 show_contacts sel1, sel2, result=&amp;quot;contacts&amp;quot;, cutoff=3.6, bigcutoff=4.0&lt;br /&gt;
&lt;br /&gt;
== Required Arguments ==&lt;br /&gt;
* '''sel1''' = first selection&lt;br /&gt;
* '''sel2''' = second selection&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Optional Arguments ==&lt;br /&gt;
* '''result''' = name of created group containing contacts&lt;br /&gt;
* '''cutoff''' = cutoff for good contacts (yellow dashes)&lt;br /&gt;
* '''bigcutoff''' = cutoff for suboptimal contacts (purple dashes)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Code ==&lt;br /&gt;
&lt;br /&gt;
Copy the following text and save it as show_contacts.py &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
'''PyMOL plugin that provides show_contacts command and GUI &lt;br /&gt;
for highlighting good and bad polar contacts. Factored out of &lt;br /&gt;
clustermols by Matthew Baumgartner.&lt;br /&gt;
The advantage of this package is it requires many fewer dependencies.&lt;br /&gt;
'''&lt;br /&gt;
from __future__ import print_function&lt;br /&gt;
&lt;br /&gt;
import sys,os&lt;br /&gt;
import tkinter.simpledialog&lt;br /&gt;
import tkinter.messagebox&lt;br /&gt;
import tkinter.filedialog&lt;br /&gt;
import Pmw&lt;br /&gt;
import tkinter&lt;br /&gt;
from tkinter import *&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
&lt;br /&gt;
DEBUG=1&lt;br /&gt;
&lt;br /&gt;
def show_contacts(selection,selection2,result=&amp;quot;contacts&amp;quot;,cutoff=3.6, bigcutoff = 4.0, SC_DEBUG = DEBUG):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    USAGE&lt;br /&gt;
    &lt;br /&gt;
    show_contacts selection, selection2, [result=contacts],[cutoff=3.6],[bigcutoff=4.0]&lt;br /&gt;
    &lt;br /&gt;
    Show various polar contacts, the good, the bad, and the ugly.&lt;br /&gt;
    &lt;br /&gt;
    Edit MPB 6-26-14: The distances are heavy atom distances, so I upped the default cutoff to 4.0&lt;br /&gt;
    &lt;br /&gt;
    Returns:&lt;br /&gt;
    True/False -  if False, something went wrong&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if SC_DEBUG &amp;gt; 4:&lt;br /&gt;
        print('Starting show_contacts')&lt;br /&gt;
        print('selection = &amp;quot;' + selection + '&amp;quot;')&lt;br /&gt;
        print('selection2 = &amp;quot;' + selection2 + '&amp;quot;')&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
    #if the group of contacts already exist, delete them&lt;br /&gt;
    cmd.delete(result)&lt;br /&gt;
&lt;br /&gt;
    # ensure only N and O atoms are in the selection&lt;br /&gt;
    all_don_acc1 = selection + &amp;quot; and (donor or acceptor)&amp;quot;&lt;br /&gt;
    all_don_acc2 = selection2 + &amp;quot; and  (donor or acceptor)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    if SC_DEBUG &amp;gt; 4:&lt;br /&gt;
        print('all_don_acc1 = &amp;quot;' + all_don_acc1 + '&amp;quot;')&lt;br /&gt;
        print('all_don_acc2 = &amp;quot;' + all_don_acc2 + '&amp;quot;')&lt;br /&gt;
    &lt;br /&gt;
    #if theses selections turn out not to have any atoms in them, pymol throws cryptic errors when calling the dist function like:&lt;br /&gt;
    #'Selector-Error: Invalid selection name'&lt;br /&gt;
    #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&lt;br /&gt;
    #the return values are the count of the number of atoms&lt;br /&gt;
    all1_sele_count = cmd.select('all_don_acc1_sele', all_don_acc1)&lt;br /&gt;
    all2_sele_count = cmd.select('all_don_acc2_sele', all_don_acc2)&lt;br /&gt;
    &lt;br /&gt;
    #print out some warnings&lt;br /&gt;
    if DEBUG &amp;gt; 3:&lt;br /&gt;
        if not all1_sele_count:&lt;br /&gt;
            print('Warning: all_don_acc1 selection empty!')&lt;br /&gt;
        if not all2_sele_count:&lt;br /&gt;
            print('Warning: all_don_acc2 selection empty!')&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    allres = result + &amp;quot;_all&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(allres, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 0)&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;, &amp;quot;0.05&amp;quot;, allres)&lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;, &amp;quot;purple&amp;quot;, allres)&lt;br /&gt;
        cmd.hide(&amp;quot;labels&amp;quot;, allres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    #compute good polar interactions according to pymol&lt;br /&gt;
    polres = result + &amp;quot;_polar&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(polres, 'all_don_acc1_sele', 'all_don_acc2_sele', cutoff, mode = 2) #hopefully this checks angles? Yes&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.126&amp;quot;,polres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    #When running distance in mode=2, the cutoff parameter is ignored if set higher then the default of 3.6&lt;br /&gt;
    #so set it to the passed in cutoff and change it back when you are done.&lt;br /&gt;
    old_h_bond_cutoff_center = cmd.get('h_bond_cutoff_center') # ideal geometry&lt;br /&gt;
    old_h_bond_cutoff_edge = cmd.get('h_bond_cutoff_edge') # minimally acceptable geometry&lt;br /&gt;
    cmd.set('h_bond_cutoff_center', bigcutoff)&lt;br /&gt;
    cmd.set('h_bond_cutoff_edge', bigcutoff)&lt;br /&gt;
        &lt;br /&gt;
    #compute possibly suboptimal polar interactions using the user specified distance&lt;br /&gt;
    pol_ok_res = result + &amp;quot;_polar_ok&amp;quot;&lt;br /&gt;
    if all1_sele_count and all2_sele_count:&lt;br /&gt;
        cmd.distance(pol_ok_res, 'all_don_acc1_sele', 'all_don_acc2_sele', bigcutoff, mode = 2) &lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;, &amp;quot;0.06&amp;quot;, pol_ok_res)&lt;br /&gt;
&lt;br /&gt;
    #now reset the h_bond cutoffs&lt;br /&gt;
    cmd.set('h_bond_cutoff_center', old_h_bond_cutoff_center)&lt;br /&gt;
    cmd.set('h_bond_cutoff_edge', old_h_bond_cutoff_edge) &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    &lt;br /&gt;
    onlyacceptors1 = selection + &amp;quot; and (acceptor and !donor)&amp;quot;&lt;br /&gt;
    onlyacceptors2 = selection2 + &amp;quot; and (acceptor and !donor)&amp;quot;&lt;br /&gt;
    onlydonors1 = selection + &amp;quot; and (!acceptor and donor)&amp;quot;&lt;br /&gt;
    onlydonors2 = selection2 + &amp;quot; and (!acceptor and donor)&amp;quot;  &lt;br /&gt;
    &lt;br /&gt;
    #perform the selections&lt;br /&gt;
    onlyacceptors1_sele_count = cmd.select('onlyacceptors1_sele', onlyacceptors1)&lt;br /&gt;
    onlyacceptors2_sele_count = cmd.select('onlyacceptors2_sele', onlyacceptors2)&lt;br /&gt;
    onlydonors1_sele_count = cmd.select('onlydonors1_sele', onlydonors1)&lt;br /&gt;
    onlydonors2_sele_count = cmd.select('onlydonors2_sele', onlydonors2)    &lt;br /&gt;
    &lt;br /&gt;
    #print out some warnings&lt;br /&gt;
    if SC_DEBUG &amp;gt; 2:&lt;br /&gt;
        if not onlyacceptors1_sele_count:&lt;br /&gt;
            print('Warning: onlyacceptors1 selection empty!')&lt;br /&gt;
        if not onlyacceptors2_sele_count:&lt;br /&gt;
            print('Warning: onlyacceptors2 selection empty!')&lt;br /&gt;
        if not onlydonors1_sele_count:&lt;br /&gt;
            print('Warning: onlydonors1 selection empty!')&lt;br /&gt;
        if not onlydonors2_sele_count:&lt;br /&gt;
            print('Warning: onlydonors2 selection empty!')    &lt;br /&gt;
            &lt;br /&gt;
    &lt;br /&gt;
    accres = result+&amp;quot;_aa&amp;quot;&lt;br /&gt;
    if onlyacceptors1_sele_count and onlyacceptors2_sele_count:&lt;br /&gt;
        aa_dist_out = cmd.distance(accres, 'onlyacceptors1_sele', 'onlyacceptors2_sele', cutoff, 0)&lt;br /&gt;
&lt;br /&gt;
        if aa_dist_out &amp;lt; 0:&lt;br /&gt;
            print('\n\nCaught a pymol selection error in acceptor-acceptor selection of show_contacts')&lt;br /&gt;
            print('accres:', accres)&lt;br /&gt;
            print('onlyacceptors1', onlyacceptors1)&lt;br /&gt;
            print('onlyacceptors2', onlyacceptors2)&lt;br /&gt;
            return False&lt;br /&gt;
    &lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;,&amp;quot;red&amp;quot;,accres)&lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.125&amp;quot;,accres)&lt;br /&gt;
    &lt;br /&gt;
    ########################################&lt;br /&gt;
    &lt;br /&gt;
    donres = result+&amp;quot;_dd&amp;quot;&lt;br /&gt;
    if onlydonors1_sele_count and onlydonors2_sele_count:&lt;br /&gt;
        dd_dist_out = cmd.distance(donres, 'onlydonors1_sele', 'onlydonors2_sele', cutoff, 0)&lt;br /&gt;
        &lt;br /&gt;
        #try to catch the error state &lt;br /&gt;
        if dd_dist_out &amp;lt; 0:&lt;br /&gt;
            print('\n\nCaught a pymol selection error in dd selection of show_contacts')&lt;br /&gt;
            print('donres:', donres)&lt;br /&gt;
            print('onlydonors1', onlydonors1)&lt;br /&gt;
            print('onlydonors2', onlydonors2)&lt;br /&gt;
            print(&amp;quot;cmd.distance('&amp;quot; + donres + &amp;quot;', '&amp;quot; + onlydonors1 + &amp;quot;', '&amp;quot; + onlydonors2 + &amp;quot;', &amp;quot; + str(cutoff) + &amp;quot;, 0)&amp;quot;)  &lt;br /&gt;
            return False&lt;br /&gt;
        &lt;br /&gt;
        cmd.set(&amp;quot;dash_color&amp;quot;,&amp;quot;red&amp;quot;,donres)  &lt;br /&gt;
        cmd.set(&amp;quot;dash_radius&amp;quot;,&amp;quot;0.125&amp;quot;,donres)&lt;br /&gt;
    &lt;br /&gt;
    ##########################################################&lt;br /&gt;
    ##### find the buried unpaired atoms of the receptor #####&lt;br /&gt;
    ##########################################################&lt;br /&gt;
    &lt;br /&gt;
    #initialize the variable for when CALC_SASA is False&lt;br /&gt;
    unpaired_atoms = ''&lt;br /&gt;
    &lt;br /&gt;
        &lt;br /&gt;
    ## Group&lt;br /&gt;
    cmd.group(result,&amp;quot;%s %s %s %s %s %s&amp;quot; % (polres, allres, accres, donres, pol_ok_res, unpaired_atoms))&lt;br /&gt;
    &lt;br /&gt;
    ## Clean up the selection objects&lt;br /&gt;
    #if the show_contacts debug level is high enough, don't delete them.&lt;br /&gt;
    if SC_DEBUG &amp;lt; 5:&lt;br /&gt;
        cmd.delete('all_don_acc1_sele')&lt;br /&gt;
        cmd.delete('all_don_acc2_sele')&lt;br /&gt;
        cmd.delete('onlyacceptors1_sele')&lt;br /&gt;
        cmd.delete('onlyacceptors2_sele')&lt;br /&gt;
        cmd.delete('onlydonors1_sele')&lt;br /&gt;
        cmd.delete('onlydonors2_sele')&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    return True&lt;br /&gt;
cmd.extend('contacts', show_contacts) #contacts to avoid clashing with cluster_mols version&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
#################################################################################&lt;br /&gt;
########################### Start of pymol plugin code ##########################&lt;br /&gt;
#################################################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
about_text = '''show_contacts was factored out of the much more full-featured cluster_mols&lt;br /&gt;
by Dr. Matt Baumgartner (https://pymolwiki.org/index.php/Cluster_mols).  It provides&lt;br /&gt;
an easy way to highlight polar contacts (and clashes) between two selections without&lt;br /&gt;
requiring the installation of additional dependencies.&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
class Show_Contacts:&lt;br /&gt;
    ''' Main Pymol Plugin Class '''&lt;br /&gt;
    def __init__(self, app):&lt;br /&gt;
        parent = app.root&lt;br /&gt;
        self.parent = parent&lt;br /&gt;
        &lt;br /&gt;
        self.app = app&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
        ############################################################################################&lt;br /&gt;
        ### Open a window with options to select to loaded objects ###&lt;br /&gt;
        ############################################################################################&lt;br /&gt;
&lt;br /&gt;
        self.select_dialog = Pmw.Dialog(parent, &lt;br /&gt;
                         buttons = ('Ok','Cancel'), &lt;br /&gt;
                         title = 'Show Contacts Plugin',&lt;br /&gt;
                         command = self.button_pressed )&lt;br /&gt;
    &lt;br /&gt;
        self.select_dialog.withdraw()&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
        #allow the user to select from objects already loaded in pymol&lt;br /&gt;
        self.select_object_combo_box = Pmw.ComboBox(self.select_dialog.interior(),&lt;br /&gt;
                                                               scrolledlist_items=[],&lt;br /&gt;
                                                               labelpos='w',&lt;br /&gt;
                                                               label_text='Select loaded object:',&lt;br /&gt;
                                                               listbox_height = 2,&lt;br /&gt;
                                                               dropdown=True)&lt;br /&gt;
        self.select_object_combo_box2 = Pmw.ComboBox(self.select_dialog.interior(),&lt;br /&gt;
                                                               scrolledlist_items=[],&lt;br /&gt;
                                                               labelpos='w',&lt;br /&gt;
                                                               label_text='Select loaded object:',&lt;br /&gt;
                                                               listbox_height = 2,&lt;br /&gt;
                                                               dropdown=True)                                                               &lt;br /&gt;
        self.select_object_combo_box.grid(column=1, row=0)&lt;br /&gt;
        self.select_object_combo_box2.grid(column=2, row=0)&lt;br /&gt;
        self.populate_ligand_select_list()&lt;br /&gt;
        self.select_dialog.show()&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
      &lt;br /&gt;
    def button_pressed(self, result):&lt;br /&gt;
        if hasattr(result,'keycode'):&lt;br /&gt;
            if result.keycode == 36:&lt;br /&gt;
                print('keycode:', result.keycode)&lt;br /&gt;
        elif result == 'Ok' or result == 'Exit' or result == None:&lt;br /&gt;
            s1 = self.select_object_combo_box.get()&lt;br /&gt;
            s2 = self.select_object_combo_box2.get()&lt;br /&gt;
            show_contacts(s1,s2,'%s_%s'%(s1,s2))&lt;br /&gt;
            self.select_dialog.withdraw()            &lt;br /&gt;
        elif result == 'Cancel' or result == None:&lt;br /&gt;
            self.select_dialog.withdraw()&lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
    def populate_ligand_select_list(self):&lt;br /&gt;
        ''' Go thourgh the loaded objects in PyMOL and add them to the selected list. '''&lt;br /&gt;
        #get the loaded objects&lt;br /&gt;
        loaded_objects = [ name for name in cmd.get_names('all') if '_cluster_' not in name ]&lt;br /&gt;
         &lt;br /&gt;
        self.select_object_combo_box.clear()&lt;br /&gt;
        self.select_object_combo_box2.clear()&lt;br /&gt;
        &lt;br /&gt;
        for ob in loaded_objects:&lt;br /&gt;
            self.select_object_combo_box.insert('end', ob)&lt;br /&gt;
            self.select_object_combo_box2.insert('end', ob)&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
def __init__(self):&lt;br /&gt;
    self.menuBar.addmenuitem('Plugin', 'command', 'Show Contacts', label = 'Show Contacts', command = lambda s=self : Show_Contacts(s))  &lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Script_Library]]&lt;br /&gt;
[[Category:Biochemical_Scripts]]&lt;br /&gt;
[[Category:Structural_Biology_Scripts]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Cchem</name></author>
	</entry>
</feed>