Autodock plugin

From PyMOLWiki
Revision as of 09:19, 10 August 2006 by Dseelig (talk | contribs) (Autodock Plugin)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Description

This plugin should help to set up docking runs with Autodock and view docking results. It has two features:

1) Setup of a docking grid for Autodock with PyMOL.

2) View the docking results.

Installation

1)Download plugin

2) PyMOL -> Plugin -> Install Plugin

Author

Daniel Seeliger

#!/usr/bin/env python

from __future__ import division
from __future__ import generators

import os,math,re
import Tkinter
from Tkinter import *
import tkMessageBox
import Pmw
from pymol import cmd,selector
import sys
from pymol.cmd import _feedback,fb_module,fb_mask,is_list,_cmd
from pymol.cgo import *
from pymol import stored
from Numeric import *
import tkColorChooser
from pymol.vfont import plain

# Python backward-compatibility...
try:
    True
except:
    True = 1
try:
    False
except:
    False = 0
#
# Cheap hack for testing purposes
#
try:
    import pymol
    REAL_PYMOL = True
except ImportError:
    REAL_PYMOL = False
    class pymol:
        class cmd:
            def load(self,name,sel=''):
                pass
            def get_names(self):
                return ['mol1','mol2','map1','map2']
            def get_type(self,thing):
                if thing.startswith('mol'):
                    return 'object:molecule'
                else:
                    return 'object:map'
                f.close()
        cmd = cmd()
    pymol = pymol()

def __init__(self):
        self.menuBar.addmenuitem('Plugin', 'command',
                                 'Launch Autodock',
                                 label='Autodock...',
                                 command = lambda s=self: Autodock(s))
        

   

# set the defaults

defaults = {
    "spacing" : '0.375',
    "xpst":'100',
    "ypst":'100',
    "zpts":'100',
    "sel":'(all)',
    "X":'0',
    "Y":'0',
    "Z":'0',
    "dx":'1.0',
    "dy":'1.0',
    "dz":'1.0',
    "csize":'0.2',
    "lwidth":'1',
    "grid":'1',
    "output":'grid.gpf',
    "dlgfile":'dock.dlg'
    }
	       



class FileDialogButtonClassFactory:
    def get(fn,filter='*'):
        """This returns a FileDialogButton class that will
        call the specified function with the resulting file.
        """
        class FileDialogButton(Tkinter.Button):
            # This is just an ordinary button with special colors.

            def __init__(self, master=None, cnf={}, **kw):
                '''when we get a file, we call fn(filename)'''
                self.fn = fn
                self.__toggle = 0
                apply(Tkinter.Button.__init__, (self, master, cnf), kw)
                self.configure(command=self.set)
            def set(self):
                fd = PmwFileDialog(self.master,filter=filter)
                fd.title('Please choose a file')
                n=fd.askfilename()
                if n is not None:
                    self.fn(n)
        return FileDialogButton
    get = staticmethod(get)





        
class Autodock:

    def __init__(self,app):
        parent = app.root
        self.parent = parent
        self.on_screen = IntVar()
        self.on_screen.set(0) # 0 box | 1 wire
        self.center = []
        self.have_box = 0
        self.colorRGB = [1,1,1]
        self.dialog = Pmw.Dialog(parent,
                                 buttons = ('Exit',),
                                 title = 'PyMOL Autodock Tools',
                                 command = self.buttonPressed)
        self.dialog.withdraw()
        Pmw.setbusycursorattributes(self.dialog.component('hull'))

        # the title

        w = Tkinter.Label(self.dialog.interior(),
                                text = 'PyMOL Autodock Tools\nDaniel Seeliger\n<http://www.mpibpc.mpg.de/groups/grubmueller/start/people/dseelig/index.html>',
                                background = 'navy',
                                foreground = 'white',
                                #pady = 20,
                                )
        w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)

        # the basic notebook

        self.notebook = Pmw.NoteBook(self.dialog.interior())
        self.notebook.pack(fill='both',expand=0,padx=3,pady=3)
        
        # the grid page
        
        page = self.notebook.add('Grid')

        # grid definiton page
        group = Pmw.Group(page,tag_text='Grid Definition')
        group.pack(fill = 'both', expand = 0, padx = 10, pady = 5)
        self.dialog.bind('<Return>',self.buttonPressed)

        # we put the parametes on the left side
        
        lgroup = Pmw.Group(group.interior(),tag_text = "Parameters")
        lgroup.pack(side='left',fill = 'both', expand = 0, padx = 10, pady = 3)

        # ... and the display stuff on the right side
        
        rgroup = Pmw.Group(group.interior(),tag_text = "Display Options")
        rgroup.pack(side='right',fill = 'both', expand = 0, padx = 10, pady = 3)

        # the left side ...

        self.space=DoubleVar()
        self.space.set(defaults['spacing'])
        self.spacefr = Tkinter.Frame(lgroup.interior())
        labSP = Label(self.spacefr,text="Grid:");
        self.splocation = Entry(self.spacefr,textvariable=self.space,bg='black',fg='green');
        self.scrSP=Scrollbar(self.spacefr,orient="horizontal",command=self.changeValueSpacing)
        labSP.pack(side=LEFT)
        self.splocation.pack(side=LEFT)
        self.scrSP.pack(side=LEFT)
        self.spacefr.pack(fill='x',padx=4,pady=1) # vertical

        self.xpts=IntVar()
        self.xpts.set(100)
        self.xptsfr = Tkinter.Frame(lgroup.interior())
        labXP = Label(self.xptsfr,text="xpts:");
        self.xptslocation = Entry(self.xptsfr,textvariable=self.xpts,bg='black',fg='green');
        self.xptsSP=Scrollbar(self.xptsfr,orient="horizontal",command=self.changeValueXpts)
        labXP.pack(side=LEFT)
        self.xptslocation.pack(side=LEFT)
        self.xptsSP.pack(side=LEFT)
        self.xptsfr.pack(fill='x',padx=4,pady=1) # vertical

        self.ypts=IntVar()
        self.ypts.set(100)
        self.yptsfr = Tkinter.Frame(lgroup.interior())
        labYP = Label(self.yptsfr,text="ypts:");
        self.yptslocation = Entry(self.yptsfr,textvariable=self.ypts,bg='black',fg='green');
        self.yptsSP=Scrollbar(self.yptsfr,orient="horizontal",command=self.changeValueYpts)
        labYP.pack(side=LEFT)
        self.yptslocation.pack(side=LEFT)
        self.yptsSP.pack(side=LEFT)
        self.yptsfr.pack(fill='x',padx=4,pady=1) # vertical

        self.zpts=IntVar()
        self.zpts.set(100)
        self.zptsfr = Tkinter.Frame(lgroup.interior())
        labZP = Label(self.zptsfr,text="zpts:");
        self.zptslocation = Entry(self.zptsfr,textvariable=self.zpts,bg='black',fg='green');
        self.zptsSP=Scrollbar(self.zptsfr,orient="horizontal",command=self.changeValueZpts)
        labZP.pack(side=LEFT)
        self.zptslocation.pack(side=LEFT)
        self.zptsSP.pack(side=LEFT)
        self.zptsfr.pack(fill='x',padx=4,pady=1) # vertical


        # put a dummy frame
        dumframe = Tkinter.Frame(page)
        dumframe.pack(fill='x',padx=4,pady=2)
        
        dum1 = Tkinter.Label(dumframe,
                               justify=LEFT,
                               text = "",
                               )
        dum1.pack(side='left')


        # the center definition
        
        radiogroups = []
        self.selmode = Tkinter.IntVar()
        self.selmode.set(0)
        radioframe = Tkinter.Frame(page)
        
        w = Pmw.Group(radioframe,
                      tag_pyclass = Tkinter.Radiobutton,
                      tag_text='Use average coordinates \nof a given selection',
                      tag_value = 0,
                      tag_variable = self.selmode)
        w.pack(fill = 'x', expand = 1, side='top')
        cw = Tkinter.Frame(w.interior())
        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
        radiogroups.append(w)
        self.selectionlist = Pmw.EntryField(w.interior(),
                                            labelpos='w',
                                            label_text='Selection: ',
                                            value=defaults['sel'],
                                            command = self.changed,
                                            )
        self.selectionlist.pack(fill='x',padx=4,pady=1,expand=0) # vertical

        
        w = Pmw.Group(radioframe,
                      tag_pyclass = Tkinter.Radiobutton,
                      tag_text='Use coordinates',
                      tag_value = 1,
                      tag_variable = self.selmode)
        w.pack(fill = 'x', expand = 1, side='top')
        cw = Tkinter.Frame(w.interior())
        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
        radiogroups.append(w)

        radioframe.pack(padx = 6, pady = 6, expand='yes', fill='both')
        Pmw.aligngrouptags(radiogroups)

        
        self.x=DoubleVar()
        self.x.set(float(defaults["X"]))
        self.y=DoubleVar()
        self.y.set(float(defaults["Y"]))
        self.z=DoubleVar()
        self.z.set(float(defaults["Z"]))
        
        self.xfr = Tkinter.Frame(w.interior())
        labX = Label(self.xfr,text="X:");
        self.xloc = Entry(self.xfr,textvariable=self.x,bg='black',fg='green');
        self.scrX=Scrollbar(self.xfr,orient="horizontal",command=self.changeValueX)
        
        
        self.yfr = Tkinter.Frame(w.interior())
        labY = Label(self.yfr,text="Y:");
        self.yloc = Entry(self.yfr,textvariable=self.y,bg='black',fg='green');
        self.scrY=Scrollbar(self.yfr,orient="horizontal",command=self.changeValueY)
        
        self.zfr = Tkinter.Frame(w.interior())
        labZ = Label(self.zfr,text="Z:");
        self.zloc = Entry(self.zfr,textvariable=self.z,bg='black',fg='green');
        self.scrZ=Scrollbar(self.zfr,orient="horizontal",command=self.changeValueZ)
        
        labX.pack(side=LEFT)
        self.xloc.pack(side=LEFT)
        self.scrX.pack(side=LEFT)
        self.xfr.pack(fill='x',padx=4,pady=1) # vertical
        labY.pack(side=LEFT)
        self.yloc.pack(side=LEFT)
        self.scrY.pack(side=LEFT)
        self.yfr.pack(fill='x',padx=4,pady=1) # vertical
        labZ.pack(side=LEFT)
        self.zloc.pack(side=LEFT)
        self.scrZ.pack(side=LEFT)
        self.zfr.pack(fill='x',padx=4,pady=1) # vertical

        self.butt1 = Pmw.ButtonBox(radioframe, padx=0)
        self.butt1.pack(side=TOP)
        self.butt1.add('Show Box',command = self.calc_box)
        self.butt1.add('Hide Box',command = self.hideBox)
        self.butt1.add('Write gpf',command = self.write_gpf)
        self.butt1.add('Write Box',command = self.write_box)
        self.butt1.add('Change Color',command=self.tk_color_dialog)
        

        # the display options
        
        radiogroups = []
        radioframe = Tkinter.Frame(rgroup.interior())

        w = Pmw.Group(radioframe,
                      tag_pyclass = Tkinter.Radiobutton,
                      tag_text='Cylindric Box',
                      tag_value = 0,
                      tag_variable = self.on_screen)
        w.pack(fill = 'x', expand = 1, side='top')
        cw = Tkinter.Frame(w.interior())
        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
        radiogroups.append(w)
        
        self.csize=DoubleVar()
        self.csize.set(float(defaults["csize"]))

        self.csizefr = Tkinter.Frame(w.interior())
        labcsize = Label(self.csizefr,text="size:");
        self.csizeloc = Entry(self.csizefr,textvariable=self.csize,bg='black',fg='green',width=15);
        self.scrcsize=Scrollbar(self.csizefr,orient="horizontal",command=self.changeValueCsize)

        labcsize.pack(side=LEFT)
        self.csizeloc.pack(side=LEFT)
        self.scrcsize.pack(side=LEFT)
        self.csizefr.pack(fill='x',padx=4,pady=1) # vertical

        w = Pmw.Group(radioframe,
                      tag_pyclass = Tkinter.Radiobutton,
                      tag_text='Wired Box',
                      tag_value = 1,
                      tag_variable = self.on_screen)
        w.pack(fill = 'x', expand = 1, side='top')
        cw = Tkinter.Frame(w.interior())
        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
        radiogroups.append(w)
        
        self.lwidth=DoubleVar()
        self.lwidth.set(float(defaults["lwidth"]))

        self.lwidthfr = Tkinter.Frame(w.interior())
        lablwidth = Label(self.lwidthfr,text="line:");
        self.lwidthloc = Entry(self.lwidthfr,textvariable=self.lwidth,bg='black',fg='green',width=15);
        self.scrlwidth=Scrollbar(self.lwidthfr,orient="horizontal",command=self.changeValueLwidth)

        lablwidth.pack(side=LEFT)
        self.lwidthloc.pack(side=LEFT)
        self.scrlwidth.pack(side=LEFT)
        self.lwidthfr.pack(fill='x',padx=4,pady=1) # vertical

        self.grid=DoubleVar()
        self.grid.set(float(defaults["grid"]))

        self.gridfr = Tkinter.Frame(w.interior())
        labgrid = Label(self.gridfr,text="grid:");
        self.gridloc = Entry(self.gridfr,textvariable=self.grid,bg='black',fg='green',width=15);
        self.scrgrid=Scrollbar(self.gridfr,orient="horizontal",command=self.changeValueGrid)

        labgrid.pack(side=LEFT)
        self.gridloc.pack(side=LEFT)
        self.scrgrid.pack(side=LEFT)
        self.gridfr.pack(fill='x',padx=4,pady=1) # vertical

        radioframe.pack(padx = 6, pady = 6, expand='yes', fill='both')
        Pmw.aligngrouptags(radiogroups)


        # the output file stuff

        self.outfile = StringVar()
        self.outfile.set(defaults['output'])
        self.outlocation = Pmw.EntryField(page,
                                          labelpos='w',
                                          label_pyclass = FileDialogButtonClassFactory.get(self.set_outfilename,filter=("*.gpf")),
                                          validate = {'validator':self.quickFileValidation,},
                                          value = defaults['output'],
                                          label_text = 'Browse:')

        self.outlocation.pack(fill = 'both', expand = 1, padx = 10, pady = 5)

        
        # Docking Results Card
        
        page = self.notebook.add('View Docked')

        # the input file
        
        group = Pmw.Group(page,tag_text='File')
        group.pack(fill = 'both', expand = 0, padx = 10, pady = 5)

        # the structure card
        
        rgroup = Pmw.Group(page,tag_text='Structures')
        rgroup.pack(fill = 'both', expand = 1, padx = 10, pady = 5)
        self.rgroup = Pmw.NoteBook(rgroup.interior())
        self.rgroup.pack(fill='both',expand=1,padx=3,pady=3)
        self.pages = {}
        self.struct_dic = {}        
        self.dlgfile = StringVar()
        self.dlgfile.set(defaults['dlgfile'])
        self.dlglocation = Pmw.EntryField(group.interior(),
                                          labelpos='w',
                                          label_pyclass = FileDialogButtonClassFactory.get(self.set_dlgfilename,filter="*.dlg"),
                                          validate = {'validator':self.quickFileValidation,},
                                          value = defaults['dlgfile'],
                                          label_text = 'Browse:')

        self.dlglocation.pack(fill = 'both', expand = 1, padx = 10, pady = 5)

        self.load_buttonbox = Pmw.ButtonBox(group.interior(), padx=0)
        self.load_buttonbox.pack(side=LEFT,expand = 1, padx = 10, pady = 5)
        self.load_buttonbox.add('Load',command=self.load_dlg)

        self.mlist = []
        self.namelist = []

        self.radiobuttons = Pmw.RadioSelect(rgroup.interior(),
                                            buttontype = 'radiobutton',
                                            orient = 'horizontal',
                                            labelpos = 'w',
                                            )
        for text in ('Show Selected',
                     'Delete Selected'):
            self.radiobuttons.add(text)
            self.radiobuttons.setvalue('Show Selected')
        self.radiobuttons.pack(padx=4,pady=1,side='top')

        self.status_line = Label(rgroup.interior(), #relief='groove',
                                 relief='sunken',
                                 font='helvetica 12', anchor='w',fg='yellow',bg='black')

        self.status_line.pack(side='left', fill='x', expand=True)
 

        # the about card
        
        page = self.notebook.add('About')
        group = Pmw.Group(page, tag_text='About PyMOL Autodock Tools')
        group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)
	text = """
  This plugin should help to set up docking runs and view docking results.

  To set up a docking grid,

  1) Load a protein structure.
  2) Select the center of the box either by giving a selection or
     the coordinates directly.
  3) Adjust the box as needed and save the *.gpf file.

  To view docking results,
  
  1) Load the protein structure.
  2) Load the *.dlg file (or multiple *dlg files).
  
  For any bug, please send a mail with description to the author.

  Many thanks to
  - Warren DeLano for everything involving PyMOL
  - The PyMOL plugin writers for providing templates
  
  Created by Daniel Seeliger (dseelig@gwdg.de)
  <http://www.mpibpc.mpg.de/groups/grubmueller/start/people/dseelig/index.html> 
  Computational Biomolecular Dynamics Group
  <http://www.mpibpc.gwdg.de/abteilungen/073/>
"""

	lfre=Frame(group.interior())
	bar=Scrollbar(lfre,)
	ll=Text(lfre,yscrollcommand=bar.set,background="#ddddff",font="Times 14")
	bar.config(command=ll.yview)

	ll.insert(END,text)
	ll.pack(side=LEFT,expand="yes",fill="both")
	bar.pack(side=LEFT,expand="yes",fill="y")
	lfre.pack(expand="yes",fill="both")

        self.notebook.setnaturalsize()

        self.showAppModal()


    # functions

    def tk_color_dialog(self):
        color = tkColorChooser.Chooser(
            initialcolor='white',title='Choose box color').show()
        if color[0] is not None:
            self.colorRGB = [color[0][0]/100.,
                             color[0][1]/100.,
                             color[0][2]/100.]
                            

        
    def status_combobox(self, value):
        name = value.split('_')[0]
        if self.radiobuttons.getvalue()=='Show Selected':
            view = cmd.get_view()
            cmd.read_pdbstr(self.struct_dic[str(value)].as_string,str(value))
            cmd.set_view(view)
            text = 'Docked Energy: %8.2f kcal/mol' % self.struct_dic[str(value)].energy
            self.status_line.configure(text=text)
            usr = self.struct_dic[str(value)].info_as_string.split('\n')
            u = ''
            for l in usr:
                u+=l[8:]+'\n'
            atoms = self.struct_dic[str(value)].as_string.split('\n')
            at = ''
            for a in atoms:
                at+=a[8:]+'\n'
                
            self.pages[name]['text'].clear()
            self.pages[name]['text'].insert('end',u)
            self.pages[name]['text'].insert('end',at)
        else:
            cmd.delete(str(value))
            self.pages[name]['text'].clear()
            self.status_line.configure(text='')
            
    def set_outfilename(self,filename):
        self.outlocation.setvalue(filename)

    def set_dlgfilename(self,filename):
        self.dlglocation.setvalue(filename)

    def buttonPressed(self,result):
        if hasattr(result,'keycode'):
            if result.keycode == 36:
                if self.notebook.getcurselection()=='Grid':
                    self.calc_box()
                elif self.notebook.getcurselection()=='View Docked':
                    self.load_dlg()
        if result == 'Show Box':
            self.calc_box()
        elif result == 'Write gpf':
            self.write_gpf()
        elif result == 'Exit' or result == None:
            self.dialog.withdraw()

    def write_gpf(self):
        fname = self.outlocation.getvalue()
        if os.path.isfile(fname):
            print "backing up %s to ~%s" % (fname,fname)
            os.rename(fname,'~'+fname)
        print 'writing file %s' % fname
        fp = self.fileopen(fname,'w')
        if fp:
            print >>fp,"receptor protein.pdbqs          #macromolecule"
            print >>fp,"gridfld  protein.maps.fld       #grid_data_file"
            print >>fp,"npts  %5d %5d %5d         #num.grid points in xyz" % \
                  (self.xpts.get(),self.ypts.get(),self.zpts.get())
            print >>fp,"spacing %7.3f                 #spacing (Angstroms)" % self.space.get()
            print >>fp,"gridcenter %6.3f %6.3f %6.3f #xyz-coordinates or \"auto\" "%\
                  (self.center[0],self.center[1],self.center[2])
            self.print_stuff(fp)
            fp.close()
        
    def write_box(self):
        self.calc_box()
        fname = self.outlocation.getvalue()
        if os.path.isfile(fname):
            print "backing up %s to ~%s" % (fname,fname)
            os.rename(fname,'~'+fname)
        print 'writing file %s' % fname
        fp = self.fileopen(fname,'w')
        print >>fp, 'xmin = %8.3f' % self.dbox[0][0]
        print >>fp, 'xmax = %8.3f' % self.dbox[0][1]
        print >>fp, 'ymin = %8.3f' % self.dbox[1][0]
        print >>fp, 'ymax = %8.3f' % self.dbox[1][1]
        print >>fp, 'zmin = %8.3f' % self.dbox[2][0]
        print >>fp, 'zmax = %8.3f' % self.dbox[2][1]
        fp.close()
    
    def print_stuff(self,fp):
        
        print >>fp, """types CANOSH                    #atom type names
smooth 0.500                    #store minimum energy within radius (Ang)
map protein.C.map               #filename of grid map
nbp_r_eps  4.00 0.0222750 12  6 #C-C lj
nbp_r_eps  3.75 0.0230026 12  6 #C-N lj
nbp_r_eps  3.60 0.0257202 12  6 #C-O lj
nbp_r_eps  4.00 0.0257202 12  6 #C-S lj
nbp_r_eps  3.00 0.0081378 12  6 #C-H lj
nbp_r_eps  4.10 0.0257202 12  6 #C-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  3.70 0.0181874 12  6 #C-M lj (Met: Mg)
sol_par 12.77 0.6844            #C atomic fragmental volume, solv. param.
constant 0.000                  #C grid map constant energy
map protein.A.map               #filename of grid map
nbp_r_eps  4.00 0.0222750 12  6 #A-C lj
nbp_r_eps  3.75 0.0230026 12  6 #A-N lj
nbp_r_eps  3.60 0.0257202 12  6 #A-O lj
nbp_r_eps  4.00 0.0257202 12  6 #A-S lj
nbp_r_eps  3.00 0.0081378 12  6 #A-H lj
nbp_r_eps  4.10 0.0257202 12  6 #A-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  3.70 0.0181874 12  6 #A-M lj (Met: Mg)
sol_par 10.80 0.1027            #A atomic fragmental volume, solv. param.
constant 0.000                  #A grid map constant energy
map protein.N.map               #filename of grid map
nbp_r_eps  3.75 0.0230026 12  6 #N-C lj
nbp_r_eps  3.50 0.0237600 12  6 #N-N lj
nbp_r_eps  3.35 0.0265667 12  6 #N-O lj
nbp_r_eps  3.75 0.0265667 12  6 #N-S lj
nbp_r_eps  2.75 0.0084051 12  6 #N-H lj
nbp_r_eps  3.85 0.0265667 12  6 #N-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  3.45 0.0187839 12  6 #N-M lj (Met: Mg)
sol_par  0.00 0.0000            #N atomic fragmental volume, solv. param.
constant 0.000                  #N grid map constant energy
map protein.O.map               #filename of grid map
nbp_r_eps  3.60 0.0257202 12  6 #O-C lj
nbp_r_eps  3.35 0.0265667 12  6 #O-N lj
nbp_r_eps  3.20 0.0297000 12  6 #O-O lj
nbp_r_eps  3.60 0.0297000 12  6 #O-S lj
nbp_r_eps  1.90 0.3280000 12 10 #O-H hb
nbp_r_eps  3.70 0.0297000 12  6 #O-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  3.30 0.0210010 12  6 #O-M lj (Met: Mg)
sol_par  0.00 0.0000            #O atomic fragmental volume, solv. param.
constant 0.236                  #O grid map constant energy
map protein.S.map               #filename of grid map
nbp_r_eps  4.00 0.0257202 12  6 #S-C lj
nbp_r_eps  3.75 0.0265667 12  6 #S-N lj
nbp_r_eps  3.60 0.0297000 12  6 #S-O lj
nbp_r_eps  4.00 0.0297000 12  6 #S-S lj
nbp_r_eps  2.50 0.0656000 12 10 #S-H hb
nbp_r_eps  4.10 0.0297000 12  6 #S-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  3.70 0.0210010 12  6 #S-M lj (Met: Mg)
sol_par  0.00 0.0000            #S atomic fragmental volume, solv. param.
constant 0.000                  #S grid map constant energy
map protein.H.map               #filename of grid map
nbp_r_eps  3.00 0.0081378 12  6 #H-C lj
nbp_r_eps  2.75 0.0084051 12  6 #H-N lj
nbp_r_eps  1.90 0.3280000 12 10 #H-O hb
nbp_r_eps  2.50 0.0656000 12 10 #H-S hb
nbp_r_eps  2.00 0.0029700 12  6 #H-H lj
nbp_r_eps  3.10 0.0093920 12  6 #H-X lj (X: Phosphorus in protein-cofactor)
nbp_r_eps  2.70 0.0066411 12  6 #H-M lj (Met: Mg)
sol_par  0.00 0.0000            #H atomic fragmental volume, solv. param.
constant 0.118                  #H grid map constant energy
elecmap protein.e.map           #electrostatic potential map
dielectric -0.1146              #<0,distance-dep.diel; >0,constant
#fmap ... .f.map                #floating grid
"""
        
    def quickFileValidation(self,s):
        if s == '': return Pmw.PARTIAL
        elif os.path.isfile(s): return Pmw.OK
        elif os.path.exists(s): return Pmw.PARTIAL
        else: return Pmw.PARTIAL

    def changed(self):
        self.selmode.set(0)
        self.calc_box()
        self.showCrisscross()
        self.selectionlist.clear()
        
    def calc_center(self):
        self.center = []
        if self.selmode.get() == 0:
            sel = self.selectionlist.getvalue()
            if sel:
                stored.xyz  = []
                cmd.iterate_state(1,sel,"stored.xyz.append([x,y,z])")
                self.center = average(stored.xyz)
            else:
                self.selmode.set(1)
                self.calc_center()

        elif self.selmode.get() == 1:
            self.center.append(float(self.x.get()))
            self.center.append(float(self.y.get()))
            self.center.append(float(self.z.get()))
        self.x.set(self.center[0])
        self.y.set(self.center[1])
        self.z.set(self.center[2])
        

    def showCrisscross(self):
        startpoint = (self.center[0],self.center[1],self.center[2])
        cmd.delete("crisscross")
        self.crisscross(startpoint[0],startpoint[1],startpoint[2],0.5,"crisscross")
        
    def changeValueSpacing(self,a):
        val = float(self.space.get())+float(a)*0.005
        self.space.set(val)
        if self.have_box:
            self.selmode.set(1)
            self.calc_center()
            self.showCrisscross()
            self.calc_box()
        
        
    def changeValueXpts(self,a):
        val = int(self.xpts.get())+int(a)
        self.xpts.set(val)
        if self.have_box:
            self.selmode.set(1)
            self.calc_center()
            self.showCrisscross()
            self.calc_box()

    def changeValueYpts(self,a):
        val = int(self.ypts.get())+int(a)
        self.ypts.set(val)
        if self.have_box:
            self.selmode.set(1)
            self.calc_center()
            self.showCrisscross()
            self.calc_box()

    def changeValueZpts(self,a):
        val = int(self.zpts.get())+int(a)
        self.zpts.set(val)
        if self.have_box:
            self.selmode.set(1)
            self.calc_center()
            self.showCrisscross()
            self.calc_box()


    def changeValueX(self,a):
        self.selmode.set(1)
        val=float(self.x.get())+float(a)*1.0
        self.x.set(val)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()
        
    def changeValueY(self,a):
        self.selmode.set(1)
        val=float(self.y.get())+float(a)*1.0
        self.y.set(val)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()
        
    def changeValueZ(self,a):
        self.selmode.set(1)
        val=float(self.z.get())+float(a)*1.0
        self.z.set(val)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()
        
    def changeValueCsize(self,a):
        val=float(self.csize.get())+float(a)*0.1
        self.csize.set(val)
        self.selmode.set(1)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()

        
    def changeValueLwidth(self,a):
        val=float(self.lwidth.get())+float(a)*1.0
        self.lwidth.set(val)
        self.selmode.set(1)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()
        
    def changeValueGrid(self,a):
        val=float(self.grid.get())+float(a)*1.0
        self.grid.set(val)
        self.selmode.set(1)
        self.calc_center()
        self.showCrisscross()
        self.calc_box()


    def calc_box(self):
        self.calc_center()
        xpts = int(self.xpts.get())
        ypts = int(self.ypts.get())
        zpts = int(self.zpts.get())
        csize = float(self.csize.get())
        spacing = float(self.space.get())
        size = [xpts*spacing,ypts*spacing,zpts*spacing]
        xmax = xmin = ymax = ymin = zmax =zmin = 0
        xmax = self.center[0] + size[0]/2.
        xmin = self.center[0] - size[0]/2.
        ymax = self.center[1] + size[1]/2.
        ymin = self.center[1] - size[1]/2.
        zmax = self.center[2] + size[2]/2.
        zmin = self.center[2] - size[2]/2.
        x = [xmin,xmax]
        y = [ymin,ymax]
        z = [zmin,zmax]
        self.dbox = [x,y,z]
        if self.on_screen.get()==0:
            self.showBox(self.dbox,csize)
        elif self.on_screen.get()==1:
            self.showWireBox(self.dbox)
        self.have_box = 1
        
    def showBox(self,box,size):
        view = cmd.get_view()
        name =" box"
        obj = []
        # do the box
        for i in range(2):
            for k in range (2):
                for j in range(2):
                    if i != 1:
                        obj.append(CYLINDER)
                        obj.extend([box[0][i],box[1][j],box[2][k]])
                        obj.extend([box[0][i+1],box[1][j],box[2][k]])
                        obj.append(size)
                        obj.extend(self.colorRGB)
                        obj.extend(self.colorRGB)
                        obj.append(COLOR)
                        obj.extend(self.colorRGB)
                        obj.append(SPHERE)
                        obj.extend([box[0][i],box[1][j],box[2][k],size])
                        
                    if j != 1:
                        obj.append(CYLINDER)
                        obj.extend([box[0][i],box[1][j],box[2][k]])
                        obj.extend([box[0][i],box[1][j+1],box[2][k]])
                        obj.append(size)
                        obj.extend(self.colorRGB)
                        obj.extend(self.colorRGB)
                        obj.append(COLOR)
                        obj.extend(self.colorRGB)
                        obj.append(SPHERE)
                        obj.extend([box[0][i],box[1][j+1],box[2][k],size])
                    if k != 1:
                        obj.append(CYLINDER)
                        obj.extend([box[0][i],box[1][j],box[2][k]])
                        obj.extend([box[0][i],box[1][j],box[2][k+1]])
                        obj.append(size)
                        obj.extend(self.colorRGB)
                        obj.extend(self.colorRGB)
                        obj.append(COLOR)
                        obj.extend(self.colorRGB)
                        obj.append(SPHERE)
                        obj.extend([box[0][i],box[1][j],box[2][k+1],size])

        axes = [[2.0,0.0,0.0],[0.0,2.0,0.0],[0.0,0.0,2.0]]
        xpos = [box[0][1]+(box[0][1]-box[0][0])/5.,box[1][0],box[2][0]]
        cyl_text(obj,plain,xpos,'X',0.10,axes=axes)
        ypos = [box[0][0],box[1][1]+(box[1][1]-box[1][0])/5,box[2][0]]
        cyl_text(obj,plain,ypos,'Y',0.10,axes=axes)
        zpos = [box[0][0],box[1][0],box[2][1]+(box[2][1]-box[2][0])/5]
        cyl_text(obj,plain,zpos,'Z',0.10,axes=axes)
        cmd.load_cgo(obj,name)
        cmd.set_view(view)
        
    def hideBox(self):
        cmd.delete("box")
        cmd.delete("wirebox")
        
    def showWireBox(self,box):
        cmd.delete("wirebox")
        view = cmd.get_view()
        spacing = float(self.grid.get())
        lwidth = float(self.lwidth.get())
        xpts = int(round((box[0][1]-box[0][0])/spacing))+1
        ypts = int(round((box[1][1]-box[1][0])/spacing))+1
        zpts = int(round((box[2][1]-box[2][0])/spacing))+1
        obj = []
        for i in range(xpts):
            for k in range (ypts):
                obj.append(BEGIN)
                obj.append(LINE_STRIP)
                obj.append(COLOR)
                obj.extend(self.colorRGB)
                
                for j in range(zpts):
                    
                    obj.append(VERTEX)
                    obj.extend([box[0][0]+spacing*i,box[1][0]+spacing*k,\
                                box[2][0]+spacing*j])

                obj.append(END)
        for i in range(xpts):
            for j in range (zpts):
                obj.append(BEGIN)
                obj.append(LINE_STRIP)
                obj.append(COLOR)
                obj.extend(self.colorRGB)
                for k in range(ypts):
                    obj.append(VERTEX)
                    obj.extend([box[0][0]+spacing*i,box[1][0]+spacing*k,\
                                box[2][0]+spacing*j])
                obj.append(END)
        for j in range(zpts):
            for i in range (xpts):
                obj.append(BEGIN)
                obj.append(LINE_STRIP)
                obj.append(COLOR)
                obj.extend(self.colorRGB)
                for k in range(ypts):
                    obj.append(VERTEX)
                    obj.extend([box[0][0]+spacing*i,box[1][0]+spacing*k,\
                                box[2][0]+spacing*j])
                obj.append(END)
        for j in range(zpts):
            for k in range (ypts):
                obj.append(BEGIN)
                obj.append(LINE_STRIP)
                obj.append(COLOR)
                obj.extend(self.colorRGB)
                for i in range(xpts):
                    obj.append(VERTEX)
                    obj.extend([box[0][0]+spacing*i,box[1][0]+spacing*k,\
                                box[2][0]+spacing*j])
                obj.append(END)
        cmd.load_cgo(obj,"wirebox")
        cmd.set("cgo_line_width",lwidth)
        cmd.set_view(view)
         
    def crisscross(self,x,y,z,d,name="crisscross"):
        
        obj = [
            LINEWIDTH, 3,
            
            BEGIN, LINE_STRIP,
            VERTEX, float(x-d), float(y), float(z),
            VERTEX, float(x+d), float(y), float(z),
            END,
            
            BEGIN, LINE_STRIP,
            VERTEX, float(x), float(y-d), float(z),
            VERTEX, float(x), float(y+d), float(z),
            END,
            
            BEGIN, LINE_STRIP,
            VERTEX, float(x), float(y), float(z-d),
            VERTEX, float(x), float(y), float(z+d),
            END
            
            ]
        view = cmd.get_view()
        cmd.load_cgo(obj,name)
        cmd.set_view(view)



    def load_dlg(self):
        filename = self.dlglocation.get()
        self.namelist = []
        name = filename.split('/')[-1].split('.')[0]
        fp=self.fileopen(filename,'r')
        if fp:
            string = fp.read()
            newl = []
            modlist = []
            ex = re.compile('DOCKED:.*')
            l = ex.findall(string)
            str = ''
            mod = []
            for i in range(len(l)):
                if 'MODEL' in l[i]:
                    str+=l[i]+'\n'
                    for k in range(i+1,len(l)):
                        if 'TER' in l[k]:
                            str+=l[k]+'\n'
                            mod.append(str)
                            str=''
                            break
                        else:
                            str+=l[k]+'\n'
                            mlist= []
            for x in mod:
                m = Model()
                m.str2mod(x)
                mlist.append(m)
            self.mlist = sortByEnergy(mlist)
            for i in range(len(self.mlist)):
                self.namelist.append(name+'_%d'%(i+1))
                self.struct_dic[name+'_%d'%(i+1)] = self.mlist[i]
            self.update_combo(name)
        
    def update_combo(self,name):
        try:
            self.rgroup.delete(name)
        except:
            pass
        self.pages[name] = {'name':self.rgroup.add(name)}
        self.pages[name].update({'structs':self.namelist})
        self.del_buttonbox = Pmw.ButtonBox(self.pages[name]['name'], padx=3)
        self.del_buttonbox.pack(fill='x',side=TOP)
        self.del_buttonbox.add('Show best 10 %s' % name,command=self.show_best_lig)
        self.del_buttonbox.add('Show all %s' % name,command=self.show_all_lig)
        self.del_buttonbox.add('Hide all %s' % name,command=self.hide_all_lig)
        self.del_buttonbox.add('Delete %s' % name,command=self.del_lig)        

        self.pages[name]['combo'] = Pmw.ComboBox(self.pages[name]['name'],
                                                 label_text='Docked',
                                                 labelpos='nw',
                                                 scrolledlist_items= self.namelist,
                                                 selectioncommand=self.status_combobox,
                                                 listbox_height=10,
                                                 listbox_width=1,
                                                 
                                                 dropdown=False)
        self.pages[name]['combo'].pack(side='left', padx=3, anchor='n')

        self.pages[name]['text'] = Pmw.ScrolledText(self.pages[name]['name'],
                                                    borderframe=5, 
                                                    vscrollmode='dynamic',
                                                    hscrollmode='dynamic',
                                                    labelpos='n',
                                                    label_text=name,
                                                    text_width=150, text_height=15,
                                                    text_wrap='none',
                                                    text_background='#000000',
                                                    text_foreground='green'
                                                    )
        self.pages[name]['text'].pack()
        self.rgroup.selectpage(name)
        self.status_line.configure(text ='Loading %s' % name)
        
    def show_all_lig(self):
        name = self.rgroup.getcurselection()
        for s in self.pages[name]['structs']:
            self.status_combobox(s)
        self.status_line.configure(text = 'Showing all %s' % name)

    def show_best_lig(self):
        name = self.rgroup.getcurselection()
        for s in self.pages[name]['structs'][:10]:
            self.status_combobox(s)
        self.status_line.configure(text = 'Showing best 10 %s' % name)

        
    def hide_all_lig(self):
        name = self.rgroup.getcurselection()
        cmd.delete(name+'*')
        self.status_line.configure(text = 'Deleted all %s' % name)
        
    def del_lig(self):
        name = self.rgroup.getcurselection()
        cmd.delete(name+'*')
        self.rgroup.delete(self.rgroup.getcurselection())
        self.status_line.configure(text = 'Deleted %s' % name)

    def fileopen(self, filename, mode):
        try:
            fp = open(filename,mode)
            return fp
        except:
            tkMessageBox.showerror('Error','Could not open file %s' % filename)
            return None
                
    def showAppModal(self):
        #self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')
        self.dialog.show()
        #self.dialog.activate(geometry = 'centerscreenalways')
	

#
# The classes PmwFileDialog and PmwExistingFileDialog and the _errorpop function
# are taken from the Pmw contrib directory.  The attribution given in that file
# is:
################################################################################
# Filename dialogs using Pmw
#
# (C) Rob W.W. Hooft, Nonius BV, 1998
#
# Modifications:
#
# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002
#    Added optional information pane at top of dialog; if option
#    'info' is specified, the text given will be shown (in blue).
#    Modified example to show both file and directory-type dialog
#
# No Guarantees. Distribute Freely. 
# Please send bug-fixes/patches/features to <r.hooft@euromail.com>
#
################################################################################
import os,fnmatch,time
import Tkinter,Pmw
#Pmw.setversion("0.8.5")

def _errorpop(master,text):
    d=Pmw.MessageDialog(master,
                        title="Error", 
                        message_text=text,
                        buttons=("OK",))
    d.component('message').pack(ipadx=15,ipady=15)
    d.activate()
    d.destroy()
    
class PmwFileDialog(Pmw.Dialog):
    """File Dialog using Pmw"""
    def __init__(self, parent = None, **kw):
	# Define the megawidget options.
	optiondefs = (
	    ('filter',    '*',              self.newfilter),
	    ('directory', os.getcwd(),      self.newdir),
	    ('filename',  '',               self.newfilename),
	    ('historylen',10,               None),
	    ('command',   None,             None),
            ('info',      None,             None),
	    )
	self.defineoptions(kw, optiondefs)
        # Initialise base class (after defining options).
	Pmw.Dialog.__init__(self, parent)

	self.withdraw()

        # Create the components.
	interior = self.interior()

        if self['info'] is not None:
            rowoffset=1
            dn = self.infotxt()
            dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)
        else:
            rowoffset=0

	dn = self.mkdn()
	dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3)
	del dn

	# Create the directory list component.
	dnb = self.mkdnb()
	dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3)
	del dnb

	# Create the filename list component.
	fnb = self.mkfnb()
	fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3)
	del fnb

	# Create the filter entry
	ft = self.mkft()
	ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3)
	del ft

	# Create the filename entry
	fn = self.mkfn()
	fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3)
	fn.bind('<Return>',self.okbutton)
	del fn

	# Buttonbox already exists
	bb=self.component('buttonbox')
	bb.add('OK',command=self.okbutton)
	bb.add('Cancel',command=self.cancelbutton)
	del bb

	Pmw.alignlabels([self.component('filename'),
			 self.component('filter'),
			 self.component('dirname')])

    def infotxt(self):
        """ Make information block component at the top """
        return self.createcomponent(
                'infobox',
                (), None,
                Tkinter.Label, (self.interior(),),
                width=51,
                relief='groove',
                foreground='darkblue',
                justify='left',
                text=self['info']
            )

    def mkdn(self):
        """Make directory name component"""
        return self.createcomponent(
	    'dirname',
	    (), None,
	    Pmw.ComboBox, (self.interior(),),
	    entryfield_value=self['directory'],
	    entryfield_entry_width=40,
            entryfield_validate=self.dirvalidate,
	    selectioncommand=self.setdir,
	    labelpos='w',
	    label_text='Directory:')

    def mkdnb(self):
        """Make directory name box"""
        return self.createcomponent(
	    'dirnamebox',
	    (), None,
	    Pmw.ScrolledListBox, (self.interior(),),
	    label_text='directories',
	    labelpos='n',
	    hscrollmode='none',
	    dblclickcommand=self.selectdir)

    def mkft(self):
        """Make filter"""
        return self.createcomponent(
	    'filter',
	    (), None,
	    Pmw.ComboBox, (self.interior(),),
	    entryfield_value=self['filter'],
	    entryfield_entry_width=40,
	    selectioncommand=self.setfilter,
	    labelpos='w',
	    label_text='Filter:')

    def mkfnb(self):
        """Make filename list box"""
        return self.createcomponent(
	    'filenamebox',
	    (), None,
	    Pmw.ScrolledListBox, (self.interior(),),
	    label_text='files',
	    labelpos='n',
	    hscrollmode='none',
	    selectioncommand=self.singleselectfile,
	    dblclickcommand=self.selectfile)

    def mkfn(self):
        """Make file name entry"""
        return self.createcomponent(
	    'filename',
	    (), None,
	    Pmw.ComboBox, (self.interior(),),
	    entryfield_value=self['filename'],
	    entryfield_entry_width=40,
            entryfield_validate=self.filevalidate,
	    selectioncommand=self.setfilename,
	    labelpos='w',
	    label_text='Filename:')
    
    def dirvalidate(self,string):
        if os.path.isdir(string):
            return Pmw.OK
        else:
            return Pmw.PARTIAL
        
    def filevalidate(self,string):
        if string=='':
            return Pmw.PARTIAL
        elif os.path.isfile(string):
            return Pmw.OK
        elif os.path.exists(string):
            return Pmw.PARTIAL
        else:
            return Pmw.OK
        
    def okbutton(self):
	"""OK action: user thinks he has input valid data and wants to
           proceed. This is also called by <Return> in the filename entry"""
	fn=self.component('filename').get()
	self.setfilename(fn)
	if self.validate(fn):
	    self.canceled=0
	    self.deactivate()

    def cancelbutton(self):
	"""Cancel the operation"""
	self.canceled=1
	self.deactivate()

    def tidy(self,w,v):
	"""Insert text v into the entry and at the top of the list of 
           the combobox w, remove duplicates"""
	if not v:
	    return
	entry=w.component('entry')
	entry.delete(0,'end')
	entry.insert(0,v)
	list=w.component('scrolledlist')
	list.insert(0,v)
	index=1
	while index<list.index('end'):
	    k=list.get(index)
	    if k==v or index>self['historylen']:
		list.delete(index)
	    else:
		index=index+1
        w.checkentry()

    def setfilename(self,value):
	if not value:
	    return
	value=os.path.join(self['directory'],value)
	dir,fil=os.path.split(value)
	self.configure(directory=dir,filename=value)
        
	c=self['command']
	if callable(c):
	    c()

    def newfilename(self):
	"""Make sure a newly set filename makes it into the combobox list"""
	self.tidy(self.component('filename'),self['filename'])
	
    def setfilter(self,value):
	self.configure(filter=value)

    def newfilter(self):
	"""Make sure a newly set filter makes it into the combobox list"""
	self.tidy(self.component('filter'),self['filter'])
	self.fillit()

    def setdir(self,value):
	self.configure(directory=value)

    def newdir(self):
	"""Make sure a newly set dirname makes it into the combobox list"""
	self.tidy(self.component('dirname'),self['directory'])
	self.fillit()

    def singleselectfile(self):
	"""Single click in file listbox. Move file to "filename" combobox"""
	cs=self.component('filenamebox').curselection()
	if cs!=():
	    value=self.component('filenamebox').get(cs)
            self.setfilename(value)

    def selectfile(self):
	"""Take the selected file from the filename, normalize it, and OK"""
        self.singleselectfile()
	value=self.component('filename').get()
        self.setfilename(value)
        if value:
	    self.okbutton()

    def selectdir(self):
	"""Take selected directory from the dirnamebox into the dirname"""
	cs=self.component('dirnamebox').curselection()
	if cs!=():
	    value=self.component('dirnamebox').get(cs)
	    dir=self['directory']
	    if not dir:
		dir=os.getcwd()
	    if value:
		if value=='..':
		    dir=os.path.split(dir)[0]
		else:
		    dir=os.path.join(dir,value)
	    self.configure(directory=dir)
	    self.fillit()

    def askfilename(self,directory=None,filter=None):
	"""The actual client function. Activates the dialog, and
	   returns only after a valid filename has been entered 
           (return value is that filename) or when canceled (return 
           value is None)"""
	if directory!=None:
	    self.configure(directory=directory)
	if filter!=None:
	    self.configure(filter=filter)
	self.fillit()
        self.canceled=1 # Needed for when user kills dialog window
	self.activate()
	if self.canceled:
	    return None
	else:
	    return self.component('filename').get()

    lastdir=""
    lastfilter=None
    lasttime=0
    def fillit(self):
	"""Get the directory list and show it in the two listboxes"""
        # Do not run unnecesarily
        if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]:
            return
        self.lastdir=self['directory']
        self.lastfilter=self['filter']
        self.lasttime=time.time()
	dir=self['directory']
	if not dir:
	    dir=os.getcwd()
	dirs=['..']
	files=[]
        try:
            fl=os.listdir(dir)
            fl.sort()
        except os.error,arg:
            if arg[0] in (2,20):
                return
            raise
	for f in fl:
	    if os.path.isdir(os.path.join(dir,f)):
		dirs.append(f)
	    else:
		filter=self['filter']
		if not filter:
		    filter='*'
		if fnmatch.fnmatch(f,filter):
		    files.append(f)
	self.component('filenamebox').setlist(files)
	self.component('dirnamebox').setlist(dirs)
    
    def validate(self,filename):
	"""Validation function. Should return 1 if the filename is valid, 
           0 if invalid. May pop up dialogs to tell user why. Especially 
           suited to subclasses: i.e. only return 1 if the file does/doesn't 
           exist"""
	return 1

class PmwExistingFileDialog(PmwFileDialog):
    def filevalidate(self,string):
        if os.path.isfile(string):
            return Pmw.OK
        else:
            return Pmw.PARTIAL
        
    def validate(self,filename):
        if os.path.isfile(filename):
            return 1
        elif os.path.exists(filename):
            _errorpop(self.interior(),"This is not a plain file")
            return 0
        else:
            _errorpop(self.interior(),"Please select an existing file")
            return 0


#===============================================================
#
# stuff to deal with dlg files

class Model:
    def __init__(self):
        self.atoms = []
        self.energy = 0.
        self.info = []
        self.num = 0
        self.as_string = ''
        self.info_as_string = ''
    def str2mod(self,string):
        list = string.split('\n')
        for line in list:
            if 'ATOM' in line:
                self.atoms.append(line.split(':')[1].strip())
                self.as_string+=line.split(':')[1].strip()+'\n'
            elif 'USER' in line:
                self.info.append(line.split(':')[1].strip())
                self.info_as_string+=line.split(':')[1].strip()+'\n'
            elif 'MODEL' in line:
                self.num = int(line.split()[2])
        for line in self.info:
            if 'Docked Energy' in line:
                x = line.split('=')[1]
                self.energy = float(x.split()[0])

    def writeMod(self,fp):
        print >>fp,'MODEL%8d' % self.num
        for at in self.atoms:
            print >>fp, at
        print >>fp,'ENDMDL'


def sortByEnergy(mlist):
    en = []
    idx = []
    for m in mlist:
        en.append(m.energy)
        idx.append(mlist.index(m))
    changed = True
    while changed:
        changed = False
        for i in range(len(en)-1):
            if en[i] > en[i+1]:
                dum = en[i+1]
                en[i+1] = en[i]
                en[i] = dum
                dum = idx[i+1]
                idx[i+1] = idx[i]
                idx[i] = dum
                changed = True
    new = []
    for i in range(len(idx)):
        new.append(mlist[idx[i]])
        new[i].num=i+1
    return new


# Create demo in root window for testing.
if __name__ == '__main__':
    class App:
        def my_show(self,*args,**kwargs):
            pass
    app = App()
    app.root = Tkinter.Tk()
    Pmw.initialise(app.root)
    app.root.title('Some Title')
    
    widget = Autodock(app)
    exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)
    exitButton.pack()
    app.root.mainloop()