This is a read-only mirror of pymolwiki.org

Autodock plugin

From PyMOL Wiki
Revision as of 13: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

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()