added pymol/UNRESInpGen.py - generates inputs for MD
authorDawid Jagiela <lightnir@chem.univ.gda.pl>
Wed, 6 Feb 2013 13:56:22 +0000 (14:56 +0100)
committerDawid Jagiela <lightnir@chem.univ.gda.pl>
Wed, 6 Feb 2013 13:56:22 +0000 (14:56 +0100)
source/pymol/UNRESInpGen.py [new file with mode: 0755]

diff --git a/source/pymol/UNRESInpGen.py b/source/pymol/UNRESInpGen.py
new file mode 100755 (executable)
index 0000000..b3d77a7
--- /dev/null
@@ -0,0 +1,843 @@
+# -*- coding: utf-8 -*-
+'''
+-------------------------------------------------------------------------------
+ UNRESInpGen.py - UNRES graphical input generator v 1.0
+-------------------------------------------------------------------------------
+
+ Written by Dawid JagieÅ‚a (lightnir@chem.univ.gda.pl)  Oct 2012 
+
+'''
+
+from pymol import cmd,stored
+from Tkinter import *
+import tkFileDialog
+import tkMessageBox 
+import Pmw
+import string
+import os
+
+UNRESInpGen_version="1.0"
+
+def __init__(self):
+       self.UNRESInpGenWindow = None 
+       try:
+               self.menuBar.addcascademenu('Plugin', 'UNRESPlugins', 'UNRESPACK Plugins', label='UNRES Plugins')
+       except:
+               pass
+
+       self.menuBar.addmenuitem('UNRESPlugins', 'command','UNRESInpGen',
+               label='UNRES Input Generator',
+               command = lambda s=self: createUNRESInpGen(s) )
+
+def createUNRESInpGen(app):
+       if (app.UNRESInpGenWindow == None):
+               app.UNRESInpGenWindow = UNRESInpGenerator(app)
+       else:
+               app.UNRESInpGenWindow.myToggle()        
+
+#=================================================================
+
+
+class UNRESInpGenerator(Toplevel):
+       global UNRESInpGen_version
+       # Class variables
+       """
+       cv = IntVar()
+       pp = IntVar()
+       cp = IntVar()
+       rv = IntVar()
+       colorize = IntVar()
+       """
+       seq_letter = IntVar()
+       writeSSbrige = IntVar()
+       OM1Val = StringVar()
+       OM2Val = StringVar()
+       objects_list = ['Select object']    
+       seq_list=[]
+       seq_length=0
+
+       weights = ['WLONG','WSCC','WSCP','WELEC','WVDWPP','WEL_LOC','WCORR4','WCORR5','WCORR6','WTURN3','WTURN4','WTURN6','WSCCOR','WSTRAIN','WBOND','WTOR','WTORD','WANG','WSCLOC','SCAL14','SCALSCP','WCORRH','CUTOFF' ]
+
+       force_fields = [ {'FF':'GAB', 'WLONG' :'1.35279', 'WSCP'   :'1.59304', 'WELEC' :'0.71534', 'WBOND' :'1.00000', 'WANG'  :'1.13873', 'WSCLOC':'0.16258', 'WTOR':'1.98599', 'WTORD':'1.57069', 'WCORRH':'0.42887', 'WCORR5':'0.00000',
+                                       'WCORR6':'0.00000', 'WEL_LOC':'0.16036', 'WTURN3':'1.68722', 'WTURN4':'0.66230', 'WTURN6':'0.00000', 'WVDWPP':'0.11371', 'WHPB':'1.00000', 'WCORR4':'0.00000', 'CUTOFF':'7.00000'},
+                   {'FF':'E0G', 'WLONG':'1.70905', 'WSCP':'2.18310', 'WELEC':'1.06684', 'WBOND':'1.00000', 'WANG':'1.17536', 'WSCLOC':'0.22070', 'WTOR':'2.65798', 'WTORD':'2.00646', 'WCORRH':'0.23541', 'WCORR5':'0.00000',
+                                       'WCORR6':'0.00000', 'WEL_LOC':'0.42789', 'WTURN3':'1.68126', 'WTURN4':'0.75080', 'WTURN6':'0.00000', 'WVDWPP':'0.27044', 'WHPB':'1.00000', 'WSCP14':'0.00000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000'},
+                   {'FF':'1L2Y_1LE1', 'WLONG' :'1.00000', 'WSCP'    :'1.23315', 'WELEC' : '0.84476', 'WBOND' :'1.00000', 'WANG'  :'0.62954', 'WSCLOC': '0.10554', 'WTOR': '1.84316', 'WTORD' : '1.26571', 'WCORRH': '0.19212', 'WCORR5': '0.00000',
+                                       'WCORR6':'0.00000', 'WEL_LOC':'0.37357', 'WTURN3':'1.40323', 'WTURN4':'0.64673', 'WTURN6':'0.00000', 'WVDWPP': '0.23173', 'WHPB': '1.00000', 'WSCCOR': '0.00000', 'CUTOFF': '7.00000', 'WCORR4': '0.00000'},
+                   {'FF':'4P',  'WSC':'1.00000', 'WSCP':'2.73684', 'WELEC':'0.06833', 'WANG':'4.15526', 'WSCLOC':'0.16761', 'WTOR':'2.99546', 'WTORD':'2.89720', 'WCORRH':'1.98989', 'WCORR5':'0.00000', 'WCORR6':'0.00000', 'WEL_LOC':'1.60072',
+                                       'WTURN3':'2.36351', 'WTURN4':'1.34051', 'WTURN6':'0.00000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
+                   {'FF':'3P',  'WSC':'1.00000', 'WSCP':'2.85111', 'WELEC':'0.36281', 'WANG':'3.95152', 'WSCLOC':'0.15244', 'WTOR':'3.00008', 'WTORD':'2.89863', 'WCORRH':'1.91423', 'WCORR5':'0.00000', 'WCORR6':'0.00000', 'WEL_LOC':'1.72128',
+                                       'WTURN3':'2.99827', 'WTURN4':'0.59174', 'WTURN6':'0.00000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
+                       {'FF':'CASP5',          'WSC':'1.00000',        'WSCP':'1.54864', 'WELEC':'0.20016', 'WANG': '1.00572', 'WSCLOC': '0.06764', 'WTOR':'1.70537', 'WTORD':'1.24442', 'WCORRH':'0.91583', 'WCORR5':'0.00607', 'WCORR6':'0.02316', 'WEL_LOC':'1.51083',
+                                       'WTURN3':'2.00764', 'WTURN4':'0.05345', 'WTURN6':'0.05282', 'WSCCOR':'0.0', 'CUTOFF': '7.00000', 'WCORR4':'0.00000' },
+                       {'FF':'ALPHABETA',      'WSC':'1.00000', 'WSCP':'1.43178', 'WELEC':'0.41501', 'WANG':'0.37790', 'WSCLOC':'0.12880', 'WTOR':'1.98784', 'WCORRH':'2.50526', 'WCORR5':'0.23873', 'WCORR6':'0.76327', 'WEL_LOC':'2.97687', 'WTURN3':'0.09261',
+                                       'WTURN4':'0.79171', 'WTURN6':'0.01074', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
+                       {'FF':'BETA', 'WSC':'1.00000', 'WSCP':'1.10684', 'WELEC':'0.70000', 'WANG':'0.80775', 'WSCLOC':'1.91939', 'WTOR':'3.36070', 'WCORRH':'2.50000', 'WCORR5':'0.99949', 'WCORR6':'0.46247', 'WEL_LOC':'2.50000', 'WTURN3':'1.80121',
+                                       'WTURN4':'4.35377', 'WTURN6':'0.10000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
+                       {'FF':'ALPHA', 'WSC':'1.00000', 'WSCP':'0.72364', 'WELEC':'1.10890', 'WANG':'0.68702', 'WSCLOC':'1.79888', 'WTOR':'0.30562', 'WCORRH':'1.09616', 'WCORR5':'0.17452', 'WCORR6':'0.36878', 'WEL_LOC':'0.19508', 'WTURN3':'0.00000',
+                                       'WTURN4':'0.55588', 'WTURN6':'0.11539', 'CUTOFF':'7.00000', 'WCORR4':'0.0000', 'WTORD':'0.00000', 'WSCCOR':'0.00000'},
+                       {'FF':'CASP3', 'WELEC':'1.50000', 'WSTRAIN':'1.00000', 'WTOR':'0.08617', 'WANG':'0.10384', 'WSCLOC':'0.10384', 'WCORR':'1.50000', 'WTURN3':'0.00000', 'WTURN4':'0.00000', 'WTURN6':'0.00000', 'WEL_LOC':'0.00000', 'WCORR5':'0.00000',
+                                       'WCORR6':'0.00000', 'SCAL14':'0.40000', 'SCALSCP':'1.00000', 'CUTOFF':'7.00000', 'WSCCOR':'0.00000'}
+       ]
+
+       one_letter ={'VAL':'V', 'ILE':'I', 'LEU':'L', 'GLU':'E', 'GLN':'Q', 'ASP':'D', 'ASN':'N', 'HIS':'H', 'TRP':'W', 'PHE':'F', 'TYR':'Y', 'ARG':'R', 'LYS':'K', 'SER':'S', 'THR':'T', 'MET':'M', 'ALA':'A', 'GLY':'G', 'PRO':'P', 'CYS':'C'}
+
+
+       def __init__(self,parent):
+               # Create the GUI window 
+               root = Toplevel.__init__(self)
+               self.config(width=400, height=300)              # create a root window
+               self.title("UNRES Input Generator v"+UNRESInpGen_version)                 # Set window title
+               self.resizable(0, 0)                                # Disable window resize
+               self.geometry('-40+40')                             # Set window placement
+
+               # Create the Balloon.
+               self.balloon = Pmw.Balloon(root)
+
+               #================================ 
+               # "Main Options" group 
+               #
+               self.gr1 = Pmw.Group(self,tag_text = 'Main options')
+               self.gr1.grid(row=0, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
+
+               # - Create title Entryfield & Label
+               #self.l1 = Label(self.gr1.interior(), text="Title:")
+               #self.l1.grid(row=0, column=0,sticky=E)
+               self.e1 = Pmw.EntryField(self.gr1.interior(),
+                       labelpos='w',
+                       label_text="Title:",
+                       validate = {'max': 80 },
+               #       value ="(Place input information here)"
+               )
+               self.e1.component('entry').config(width=80)
+               self.e1.grid(row=0, column=0,columnspan=4, sticky=E)
+
+               # - Create "choose method" OptionMenu
+               self.OM1Val.set('MD')
+               self.optmenu1 =  Pmw.OptionMenu(self.gr1.interior(),
+                       labelpos = 'w',
+                       label_text = 'Choose method:',
+                       menubutton_textvariable = self.OM1Val,
+                       items = ['MD', 'MREMD' ],
+                       command = self.switch_options,
+                       menubutton_width = 10
+               )
+               self.optmenu1.grid(row=1, column=0,columnspan=2, sticky=E)
+       
+
+               # - Seed entryfield
+               self.gr1.e1 = Pmw.EntryField(self.gr1.interior(),
+                       labelpos='w',
+                       label_text="Seed",
+                       validate = {'validator' : 'integer', 'min': -2147483648 , 'max' : 0 },
+                       value = "-1111333"
+               )
+               self.gr1.e1.component('entry').config(width=8)
+               self.gr1.e1.grid(row=1, column=2, sticky=W)
+               #==================================
+               # - MD options frame
+               #
+               self.gr1.md = Frame(self.gr1.interior())
+               self.gr1.md.grid(row=2, column=0, columnspan=4,sticky=W+E)
+               
+               # -- nstep entryfield
+               self.gr1.md.e1 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="NSTEP",
+                       validate = {'validator' : 'integer', 'min': 1 , 'max' : 1000000 },
+                       value = "500000"
+               )
+               self.balloon.bind(self.gr1.md.e1,'Number of calculation steps')
+               self.gr1.md.e1.component('entry').config(width=8)
+               self.gr1.md.e1.grid(row=0, column=0, sticky=E)
+
+               # -- ntwe entryfield
+               self.gr1.md.e2 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="NTWE",
+                       validate = {'validator' : 'integer', 'min': 0 , 'max' : 1000000 },
+                       value = "100"
+               )
+               self.balloon.bind(self.gr1.md.e2,'Frequency of energy output.\nNTWE=0 means no energy dump. ')
+               self.gr1.md.e2.component('entry').config(width=8)
+               self.gr1.md.e2.grid(row=0,column=1, sticky=E)
+
+               # -- ntwx entryfield
+               self.gr1.md.e3 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="NTWX",
+                       validate = {'validator' : 'integer', 'min': 1 , 'max' : 1000000 },
+                       value = "1000"
+               )
+               self.balloon.bind(self.gr1.md.e3, "Frequency of coordinate output.")
+               self.gr1.md.e3.component('entry').config(width=8)
+               self.gr1.md.e3.grid(row=0,column=2, sticky=E)
+
+               # -- dt entryfield
+               self.gr1.md.e4 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="DT",
+                       validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
+                       value = "0.1")
+               self.balloon.bind(self.gr1.md.e4, "Time step. \nThe unit is \"molecular time unit\" (mtu)\n 1 mtu = 48.9 fs")
+               self.gr1.md.e4.component('entry').config(width=8)
+               self.gr1.md.e4.grid(row=0,column=3, sticky=E)
+
+               # -- damax entryfield
+               self.gr1.md.e5 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="DAMAX",
+                       validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
+                       value = "1.0")
+               self.balloon.bind(self.gr1.md.e5, "Maximum allowed change of acceleration during a single time step.\nThe time step gets scaled down, if this is exceeded.")
+               self.gr1.md.e5.component('entry').config(width=8)
+               self.gr1.md.e5.grid(row=1,column=0, sticky=E)
+
+               # -- dvmax entryfield
+               self.gr1.md.e6 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="DVMAX",
+                       validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
+                       value = "20.0")
+               self.balloon.bind(self.gr1.md.e6, "Maximum allowed velocity (in A/mtu).")
+               self.gr1.md.e6.component('entry').config(width=8)
+               self.gr1.md.e6.grid(row=1,column=1, sticky=E)
+
+               # -- restet_vel entryfield
+               self.gr1.md.e7 = Pmw.EntryField(self.gr1.md,
+                       labelpos='w',
+                       label_text="RESET_VEL",
+                       validate = {'validator' : 'integer', 'min': 0 , 'max' : 10000000 },
+                       value = "1000")
+               self.balloon.bind(self.gr1.md.e7, "Frequency of resetting velocities to values from Gaussian distribution")
+               self.gr1.md.e7.component('entry').config(width=8)
+               self.gr1.md.e7.grid(row=1,column=2, sticky=E)
+
+
+               #=================================
+               #  - thermostat frame
+               #
+               self.gr1.th = Frame(self.gr1.interior())
+               self.gr1.th.grid(row=3, column=0, columnspan=5,sticky=W+E)
+
+               # -- Thermostat optionmenu 
+               self.gr1.th.optmenu1 =  Pmw.OptionMenu(self.gr1.th,
+                       labelpos = 'w',
+                       label_text = 'thermostat',
+                       items = ['Berendsen', 'Nose-Poincare 1999','Nose-Poincare 2001', 'Nose-Hoover', 'Langevin' ],
+                       command=self.set_thermostat,
+                       menubutton_width = 15
+               )
+               self.gr1.th.optmenu1.pack(side=LEFT)#grid(row=0, column=0, sticky=E)
+
+               # -- t_bath entryfield
+               self.gr1.th.e1 = Pmw.EntryField(self.gr1.th,
+                       labelpos='w',
+                       label_text="T_BATH",
+                       validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 10000 },
+                       value = "300.0")
+               self.balloon.bind(self.gr1.th.e1, "Temperature (in K) of canonical simulation.")
+               self.gr1.th.e1.component('entry').config(width=8)
+               self.gr1.th.e1.pack(side=LEFT)
+               
+               # -- tau_bath entryfield
+               self.gr1.th.e2 = Pmw.EntryField(self.gr1.th,
+                       labelpos='w',
+                       label_text="TAU_BATH",
+                       validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 1000000 },
+                       value = "1.0")
+               self.balloon.bind(self.gr1.th.e2, "(units are mtus; 1mtu=48.9 fs) \nConstant of the coupling to the thermal bath")
+               self.gr1.th.e2.component('entry').config(width=8)
+               self.gr1.th.e2.pack(side=LEFT)
+                                
+               # -- q_np entryfield
+               self.gr1.th.e3 = Pmw.EntryField(self.gr1.th,   
+                       labelpos='w',
+                       label_text="Q_NP",
+                       validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 1000000 },
+                       value = "0.1")
+               self.balloon.bind(self.gr1.th.e3, "Mass of the fictitious particle in the calculations with the Nose-Poincare & Nose-Hoover thermostats.")
+               self.gr1.th.e3.component('entry').config(width=8)
+               #self.gr1.th.e2.pack(side=LEFT)
+
+
+               #================================= 
+               # "Force field options" group
+               #     
+               self.gr2 = Pmw.Group(self,tag_text = 'Force field options')
+               self.gr2.grid(row=2, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
+
+               # - Create "force field parameters" Option menu
+               self.OM2Val.set('Custom')
+               self.optmenu2 = Pmw.OptionMenu(self.gr2.interior(),
+               label_text = 'Force field parameters:',
+                       labelpos = 'w',
+                       menubutton_textvariable = self.OM2Val,
+                       items = ['Custom','GAB','E0G', '1L2Y_1LE1','4P','3P','CASP5','ALPHABETA','BETA','ALPHA','CASP3' ],
+                       initialitem = 'Custom',
+                       menubutton_width = 10,
+                       command=self.set_force_field
+               )
+               self.optmenu2.grid(row=0, column=0,columnspan=4,sticky=E)
+
+               # Force field parameters Entry Fields   
+               self.ef = []
+               for i in range(0,len(self.weights)):
+                       self.ef.append(Pmw.EntryField(self.gr2.interior(), 
+                       labelpos='n',
+                       label_text=self.weights[i],
+                       validate = {'validator' : 'real','min' : 0, 'max' : 10, 'minstrict' : 0},
+                       value = '1.00000'))
+                       self.ef[i].component('entry').config(width=8)
+                       self.ef[i].grid(row=1+(i//9), column=0+(i % 9))
+               # "Sequence" group 
+               self.gr3 = Pmw.Group(self,tag_text = 'Sequence')
+               self.gr3.grid(row=3, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
+                               
+               self.gr3.f1 = Frame(self.gr3.interior())
+               # Object List  
+               self.cb2 = Pmw.ComboBox(self.gr3.f1,
+                       labelpos = 'w',
+                       #entry_relief = 'raised',
+                       label_text = 'Selection/Object',
+                       scrolledlist_items = self.objects_list
+               )
+               self.cb2.pack(side=LEFT)
+               # refresh button
+               self.gr3.btn1 = Button(self.gr3.f1, text='Refresh', padx=0, pady=0 , command = self.refresh_list)
+               self.gr3.btn1.pack(side=LEFT)  
+               # Get sequence button 
+               self.gr3.btn2 = Button(self.gr3.f1, text='Get Sequence', padx=0, pady=0 , command = self.get_seq)
+               self.gr3.btn2.pack(side=LEFT)  
+                       
+               self.gr3.f1.pack(expand="yes",fill="both")
+
+               # Disulfide brige checkbox
+               self.gr3.chk = Checkbutton(self.gr3.f1, text="Write disulfide bridges", variable=self.writeSSbrige)
+               self.gr3.chk.pack(side=LEFT)
+
+               # Sequence text
+               self.gr3.t1 = Pmw.ScrolledText(self.gr3.interior(),
+                       columnheader = 1,
+                       columnheader_width = 3,
+                       rowheader = 1,
+                       rowheader_width = 4,
+                       usehullsize=1,
+                       hull_width=30,
+                       hull_height=180,
+                       text_padx = 4,
+                       text_pady = 4,
+                       Header_padx = 4,
+                       rowheader_pady = 4,
+               )
+               # Sequence text - create the header line 
+               headerline = ''
+               for column in range(1,21):
+                       headerline = headerline + ('%-4s' % str(column) )
+               self.gr3.t1.component('columnheader').insert('0.0',headerline)
+
+               self.gr3.t1.pack(expand="yes",fill="both") 
+
+               # Add some buttons
+               btn3=Button(self, text='Write Input', padx=0, pady=0, command = self.ok)
+               btn3.grid(row=10, column=0, columnspan=2,sticky=N+W+S+E)
+               btn4=Button(self, text='Close', padx=0, pady=0, command = self.myHide)
+               btn4.grid(row=10, column=2, columnspan=2,sticky=N+W+S+E)
+
+               # create callback to prevent window kill
+               self.protocol("WM_DELETE_WINDOW", self.myHide)
+
+       def ToggleColor(self):
+               if self.colorize.get()==1:
+                       for i in range(0,len(self.res_states)):
+                               UNRESInpGenWindow.ccb[i].config(state=ACTIVE, bg=self.res_states[i][1], activebackground=self.res_states[i][1], relief=RAISED, overrelief=RAISED)
+               else:
+                       for i in range(0,len(self.res_states)):
+                               UNRESInpGenWindow.ccb[i].config(state=DISABLED, bg=self.Default_Color , activebackground=self.Default_Color, relief=RAISED, overrelief=RAISED)
+
+       def myShow(self):
+               self.deiconify()
+
+       def myHide(self):
+               self.withdraw()
+
+       def myToggle(self):
+               if self.state() == "normal":
+                       self.myHide()
+               elif self.state() == "withdrawn":
+                       self.myShow()
+       
+       def get_selections(self):
+               self.objects_list = []
+               for item in cmd.get_names("all"):
+                       if cmd.get_type(item)=="object:molecule":
+                               self.objects_list.append(item)
+                       if cmd.get_type(item)=="selection":
+                               if item[0]<>"_":
+                                       self.objects_list.append(item)
+
+       def get_nonstandard(self):
+               stored.list=[]
+               cmd.iterate("(all)","stored.list.append(resn)")
+               stored.list=list(Set(stored.list))  # remove duplicates
+               # Remove standard amino acids and water from list
+               for m in ['HIS','ASP','ARG','PHE','ALA','CYS','GLY','GLN','GLU','LYS','LEU','MET','ASN','SER','TYR','THR','ILE','TRP','PRO','VAL','HOH']:
+                       try:
+                               stored.list.remove(m)
+                       except ValueError:
+                               pass
+               UNRESInpGenWindow.cbcr1.setlist(stored.list)
+
+       def refresh_list(self):
+               # Save old values
+               old = self.objects_list
+               try:
+                       old_cb2=self.cb2.getvalue()[0]
+               except:
+                       old_cb2=''
+               self.get_selections()
+
+               # Update selectionlist if needed
+               if not(old==self.objects_list):
+                       self.cb2.setlist(self.objects_list)
+                       self.cb2.setlist(self.objects_list)
+
+               if not(old_cb2 in self.objects_list):
+                       # No - clear the combobox entry
+                       self.cb2.component('entryfield').clear()
+               else:
+                       # Yes - set the old value
+                       self.cb2.selectitem(old_cb2,setentry=1)
+       
+       
+       def get_seq(self):
+               # Get the number of chains 
+               try: 
+                       nchains=int(len(cmd.get_chains(self.cb2.getvalue()[0])))
+               except:
+                       nchains=0
+               pass
+               
+               if (nchains>0):
+                       self.seq_list=[]
+               offset=0
+               seq_data=''
+               self.seq_length=0
+               for chain in range(0,nchains):
+                       # Get only amonoacids, N-terminus acyl and C-terminus amide
+                       # example:      (1uRC and chain F and (n. ca or (resn ACE and n. C) or (resn NH2 and n. N)))
+                       # No chain information or only one chain
+                       if nchains==1:
+                               atomchain=cmd.get_model(str(self.cb2.getvalue()[0])+" & (n. ca|(resn ACE & n. C)|(resn NH2+NHH+NME & n. N))").atom
+                       # Chain information is present
+                       else:
+                               atomchain=cmd.get_model(str(self.cb2.getvalue()[0])+" & chain "+cmd.get_chains(self.cb2.getvalue()[0])[chain]+" & (n. ca|(resn ACE & n. C)|(resn NH2+NHH+NME & n. N))").atom
+                       # dodaj separator lancuchow
+                       if chain>0:
+                               self.seq_list.append("D  ")
+                               self.seq_length+=1
+                               
+
+                       # Zamiana chronionych
+                       # ACE ALA ALA NH2 D   ACE ALA ALA NH2
+                       # GLY ALA ALA GLY D   GLY ALA ALA GLY
+                       # Zamiana niechronionych 
+                       #     ALA ALA     D       ALA ALA
+                       # D   ALA ALA     D       ALA ALA D
+                       #
+                       # j - licznik pozycji reszty
+                       j=0
+                       for i in atomchain:
+                               self.seq_length+=1
+                               if str(i.resn)=="NH2":
+                                       self.seq_list.append("GLY")
+                               elif str(i.resn)=="NHH":
+                                       self.seq_list.append("GLY")
+                               elif str(i.resn)=="NME":
+                                       self.seq_list.append("GLY")
+                               elif str(i.resn)=="ACE":
+                                       self.seq_list.append("GLY")
+                               elif str(i.resn)=="GLY":
+                                       self.seq_list.append("GLY")
+                               else:
+                                       if j==0 and chain==0: 
+                                               self.seq_list.append("D  ")     
+                                               self.seq_list.append(str(i.resn))
+                                               self.seq_length+=1
+                                       elif j==len(atomchain)-1 and chain==(nchains-1):
+                                               self.seq_list.append(str(i.resn))
+                                               self.seq_list.append("D  ")
+                                               self.seq_length+=1
+                                       else:
+                                               self.seq_list.append(str(i.resn))
+                               j+=1
+               rows=0
+               #row_header='0'  - old header
+               row_header='1'
+               # tag setup 
+               self.gr3.t1.tag_configure('dummy', background = 'LightBlue1')
+               tagList=[]
+               self.gr3.t1.tag_configure('cysteine', background = 'LightGoldenrod1')
+               CysTagList=[]
+
+               for i in range(len(self.seq_list)):
+                       # Dummy tag
+                       if self.seq_list[i]=="D  ":
+                               tag1 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80))
+                               tag2 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80)+3)
+                               tagList.append(tag1)
+                               tagList.append(tag2)
+                       # Cysteine tag  
+                       if self.seq_list[i]=="CYS" or self.seq_list[i]=="CYX":
+                               tag1 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80))
+                               tag2 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80)+3)
+                               CysTagList.append(tag1)
+                               CysTagList.append(tag2)
+                       #       
+                       offset+=1
+                       seq_data=seq_data+self.seq_list[i]+" "
+                       # Line Wrap
+                       if offset>19:
+                               offset=0
+                               seq_data=seq_data+'\n'
+                               rows+=1
+                               #row_header=row_header+'\n'+str(rows*20)    - old header
+                               row_header=row_header+'\n'+str(rows+1)
+
+               self.gr3.t1.clear()
+               self.gr3.t1.insert('end',seq_data)
+               # Apply tags
+               if len(tagList): 
+                       apply(self.gr3.t1.tag_add, ('dummy',) + tuple(tagList))
+               if len(CysTagList):
+                       apply(self.gr3.t1.tag_add, ('cysteine',) + tuple(CysTagList))
+
+               # Show row header
+               self.gr3.t1.component('rowheader').delete(1.0, END)
+               self.gr3.t1.component('rowheader').insert('end',row_header)     
+
+    
+       def switch_options(self,calctype):
+               '''
+                       Displays the options available to set depending on the currently 
+                       selected calculation type
+               '''
+               # Hide all
+               self.gr1.th.grid_remove()
+               self.gr1.md.grid_remove()
+               if  self.OM1Val.get()=="MD":
+                       self.gr1.md.grid(row=2, column=0, columnspan=5, sticky=W+E)
+                       self.gr1.th.grid(row=3, column=0, columnspan=5, sticky=W+E)
+               
+
+       def set_force_field(self, pole):
+               '''
+                       Enables/disables entryfields for force field perameters depending
+                       on the currently selected force field 
+               '''
+               for ff in self.force_fields:
+                       if ff['FF']==pole: 
+                               #print ff
+                               for i in range(0,len(self.weights)):
+                                       if ff.has_key(self.weights[i]):
+                                               self.ef[i].setvalue(ff.get(self.weights[i]))
+                                               self.ef[i].component('entry').config(state=NORMAL)
+                                       else:
+                                               self.ef[i].component('entry').config(state=DISABLED)
+                       # Custom force field
+                       elif pole=='Custom':
+                               for i in range(0,len(self.weights)):
+                                       self.ef[i].component('entry').config(state=NORMAL)
+
+       def set_thermostat(self,thermostat):
+               '''
+                       Display additional widget acording to selected thermostat
+               '''
+               #print thermostat
+               self.gr1.th.e2.pack_forget()
+               self.gr1.th.e3.pack_forget()
+               if thermostat=='Berendsen':
+                       self.gr1.th.e2.pack(side=LEFT)
+               elif thermostat=='Nose-Poincare 1999' or thermostat=='Nose-Poincare 2001' or thermostat=='Nose-Hoover':
+                       self.gr1.th.e3.pack(side=LEFT)
+
+       def fortran_format(self,s):
+               '''
+                   Formats string containing keywords to wrap over 80 columns 
+               '''
+               tmpstr=''
+               column=1
+               for k in s.split():
+                       if column+len(k)+1<80:
+                               tmpstr+=k+' '
+                               column+=len(k)+1
+                       else:
+                               tmpstr+=" "*(80-column)+"&\n"+k+" "
+                               column=len(k)+2
+               tmpstr+='\n'
+               return tmpstr
+
+       def get_weights(self):
+               '''
+                       Get the force field weights
+               '''
+               s = ''
+               for i in range(0,len(self.weights)):
+                       if self.ef[i].component('entry').cget("state")=="normal":
+                               s+=self.weights[i]+"="+self.ef[i].getvalue()+" "
+               return s
+
+       def get_md_opt(self):
+               s = "NSTEP="+self.gr1.md.e1.getvalue()+" NTWE="+self.gr1.md.e2.getvalue()+" "
+               s+= "NTWX="+self.gr1.md.e3.getvalue()+" DT="+self.gr1.md.e4.getvalue()+" "
+               s+= "DAMAX="+self.gr1.md.e5.getvalue()+" DVMAX="+self.gr1.md.e6.getvalue()+" " 
+               s+= "RESET_VEL="+self.gr1.md.e7.getvalue()+" " 
+               
+               # Thermostat options
+               term=self.gr1.th.optmenu1.getvalue()
+               #print term
+               if term=="Berendsen":
+                       s+="TBF TAU_BATH="+self.gr1.th.e2.getvalue()+" "
+               elif term=="Nose-Poincare 1999":
+                       s+="NOSEPOINCARE99 Q_NP="+self.gr1.th.e3.getvalue()+" "
+               elif term=="Nose-Poincare 2001":
+                       s+="NOSEPOINCARE01 Q_NP="+self.gr1.th.e3.getvalue()+" "
+               elif term=="Nose-Hoover":
+                       s+="NOSEHOOVER96 Q_NP="+self.gr1.th.e3.getvalue()+" "
+               elif term=="Langevin":
+                       s+="LANG=1 "
+
+               s+="T_BATH="+self.gr1.th.e1.getvalue()+" "
+               return s
+
+
+       def get_seq_data(self):
+               '''
+                       Dumps the sequence and disulfide bridge information
+               '''
+               # write sequence length 
+               s = str(self.seq_length)+"\n"
+               # 
+               #try: 
+               #       nchains=int(len(cmd.get_chains(self.cb2.getvalue()[0])))
+               #except:
+               #       nchains=0
+               #pass
+
+               chains=cmd.get_chains(self.cb2.getvalue()[0])
+               nchains=len(chains)
+               #print "chains  : ",chains
+               #print "nchains : ",nchains
+
+               # apply one space before each sequence line 
+               seq=self.gr3.t1.get()
+               for line in seq.split('\n'):
+                       s+=" "+line+"\n"
+               # remove last newline character
+               s = s[:-1]
+
+               # disulfide bridges - get half-cysteines by selection:
+        # sele (bto. ((object) & r. CYS+CYX & n. SG) )& n. SG
+               ncys=cmd.get_model("(bto. (("+str(self.cb2.getvalue()[0])+") & r. CYS+CYX & n. SG)) & n. SG").atom
+               nSSbr=len(ncys)/2
+       
+               
+               # Is "Write disulfide brige" checked?
+               # yes
+               if self.writeSSbrige.get():
+                       # write number of half-cysteines
+                       s+=str(len(ncys))+"\n"
+                       if len(ncys)==0:
+                               # No half-cysteines, cys position = 0  
+                               s+=" 0\n"
+                       else:
+                               # Write half-cysteine positions in sequence
+                               #       
+                               # get first chain
+                               first=cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+str(chains[0])+" & n. ca")
+                       
+                               # calculate base offset in first chain (if dummy atom present offset = 1 )      
+                               if first.atom[0].resn=="GLY":
+                                       boff=0
+                               else: 
+                                       boff=1 
+                       
+                               # create dictionary of PDB chain/resi to UNRES_index
+                               unresidx={}
+                               for c in ncys:
+                                       # calculate residue index offset from first residue in chain containing half-cysteine
+                                       fresinchain=cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+c.chain+" & n. ca").atom
+                                       roff=int(c.resi)-int(fresinchain[0].resi)+1
+                               
+                                       resb=0
+                                       coff=0
+                                       for r in chains:
+                                               if c.chain==r:
+                                                       break
+                                               resb+=len(cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+r+" & n. ca").atom)
+                                               coff+=1
+                                       # add key/value to dictionary
+                                       unresidx[c.chain+"/"+str(c.resi)]=boff+resb+coff+roff   
+                                       s+=" "+str(boff+resb+coff+roff)
+                               s+="\n"
+
+                               # Write the number of disulfide bridges
+                               s+=" "+str(nSSbr)+"\n"
+                       
+                               lista_mostkow=[]
+                               for c in ncys:
+                                       # get neibhoring Sulfur atom
+                                       opis=c.chain+str(c.resi)
+                                       lista_mostkow.append(opis)
+                                       nbr=cmd.get_model("(bto. ("+str(self.cb2.getvalue()[0])+" & resi "+str(c.resi)+"& n. SG & chain "+str(c.chain)+")) & n. SG").atom[0]
+                                       opis2=nbr.chain+str(nbr.resi)
+                                       if opis2 not in lista_mostkow:
+                                               # Write witch half-cysteines build the i-th disulfide bridge
+                                               s+=" "+str(unresidx[c.chain+"/"+str(c.resi)])+" "+str(unresidx[nbr.chain+"/"+str(nbr.resi)])+"\n"
+                                               #print c.chain, c.resn,c.resi,"-S-S-", nbr.chain, nbr.resn,nbr.resi
+               # Don't writeSSbrige    
+               else:
+                       s+="0\n 0\n"
+                               
+
+               return s
+
+
+       def write_cshell(self, cshname,prefix):
+               '''
+                       Writes the C-shell script needed to run UNRES calculations
+               '''
+               s='#!/bin/csh -f\n#\n# C-shell script generated by UNRESInpGen.py\n#\n'
+               
+               # number of processors per energy
+               if self.OM1Val.get()=="MD":
+                       s+='setenv FGPROCS 1\n'
+
+               # Potential
+               if self.OM2Val.get()=="CASP3":
+                       s+='setenv POT LJ\n'
+               else:
+                       s+='setenv POT GB\n'
+
+               # input file
+               s+='setenv PREFIX '+prefix+'\n'
+
+               # Parallel stuff
+               s+='setenv OUT1FILE YES\n'
+
+               # force filed parameters
+               s+='#---------------------------------------------------------------------\n'
+               s+='setenv DD $UNRES_ROOT/PARAM\n'
+
+               if self.OM2Val.get()=="CASP3":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_cryst.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_LJ.parm\n'
+                       s+='setenv ELEPAR $DD/electr.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_GAP.parm\n'
+                       s+='setenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="ALPHA" or self.OM2Val.get()=="BETA" or self.OM2Val.get()=="ALPHABETA":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_ecepp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_GB.parm\n'
+                       s+='setenv ELEPAR $DD/electr.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_GAP.parm\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="CASP5":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_GB.parm\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_iter7n_c\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="3P":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.3P7_iter81_1r\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_hc_iter3_3\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="4P":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.4P5_iter33_3r\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_hc_iter3_3\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="GAB":
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.1gab_3S_qclass5no310-shan2-sc-16-10-8k\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_hc_iter3_3\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="E0G":  
+                       s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.1e0g-52-17k-2k-newclass-shan1e9_gap8g-sc\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_hc_iter3_3\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="1L2Y_1LE1":
+                       s+='setenv BONDPAR $DD/bond_AM1.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/rotamers_AM1_aura.10022007.parm\n'
+                       s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_$POT.parm\n'
+                       s+='setenv ELEPAR $DD/electr_631Gdp.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_opt.parm.1igd_hc_iter3_3\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
+               elif self.OM2Val.get()=="Custom":
+                       s+='setenv BONDPAR $DD/.parm\nsetenv THETPAR $DD/.parm\nsetenv ROTPAR $DD/.parm\n'
+                       s+='setenv TORPAR $DD/.parm\nsetenv TORDPAR $DD/.parm\nsetenv SIDEPAR $DD/.parm\n'
+                       s+='setenv ELEPAR $DD/.parm\nsetenv SCPPAR $DD/.parm\nsetenv FOURIER $DD/.parm\nsetenv SCCORPAR $DD/.parm\n'
+
+
+
+               s+='setenv PATTERN $DD/patterns.cart\n'
+               s+='#---------------------------------------------------------------------\n'
+               s+='$UNRES_BIN $*\n'
+
+               f = open(cshname, 'w')
+               f.write(s)
+               f.close()
+
+
+       def setenv_info(self):
+               print '''IMPORTANT: Remember to set the following envirament variables for your shell before starting calculations:
+                 UNRES_ROOT - the root directory where UNRES is installed on your system (should contain PARAM directory)
+                 UNRES_BIN  - the UNRES binary you want to execute
+               '''
+
+
+       def ok(self):
+               '''
+                   Writes the actual input     
+               '''
+               myFormats = [
+                   ('Input files','*.inp'),
+                       ('All files','*.*')
+               ]
+               # Write error handling for empty sequence
+               #
+               s=self.gr3.t1.getvalue()
+               if len(s.strip())==0:
+                       tkMessageBox.showerror("NEED SEQUENCE DATA!", "NEED SEQUENCE DATA!\n\nYou have not loaded the sequence information. Please click \"Refresh\", choose an object from the list and click \"Get sequence\".")
+               else:                           
+                       # Display dialog window
+                       fout = tkFileDialog.asksaveasfile(parent=self,mode='w',filetypes=myFormats,title='Save input')
+                       if fout:
+                               print "Saving input file %s" % fout.name
+                               # Get input header
+                               text2save=self.fortran_format(self.e1.get())
+                               # Get main options
+                               mainopt="SEED="+self.gr1.e1.get()+" "
+                               if self.OM1Val.get()=="MD":
+                                       mainopt+="MD PDBREF EXTCONF"
+                               elif self.OM1Val.get()=="MREMD":
+                                       mainopt+="RE "
+                               text2save+=self.fortran_format(mainopt)
+                               # Get aux options
+
+                               if self.OM1Val.get()=="MD":
+                                       text2save+=self.fortran_format(self.get_md_opt())
+
+                               # Get force fields parameters
+                               text2save+=self.fortran_format(self.get_weights())
+               
+                               # PDB reference
+                               pdbreffn=str(self.cb2.getvalue()[0])+"_pdbref.pdb"
+                               text2save+=pdbreffn+"\n"
+                               print "Saving PDB reference structure %s" % (os.path.join(os.path.dirname(fout.name),pdbreffn))
+                               cmd.save(os.path.join(os.path.dirname(fout.name),pdbreffn), self.cb2.getvalue()[0])
+
+                               # C-shell script 
+                               cshellfn=os.path.join(os.path.dirname(fout.name),"unres_"+os.path.basename(os.path.splitext(fout.name)[0])+".csh")
+                               print "Writing C-shell script %s" % (cshellfn)
+                               prefix=os.path.basename(os.path.splitext(fout.name)[0])
+                               self.write_cshell(cshellfn,prefix)
+                               
+                               # Get sequence data
+                               text2save+=self.get_seq_data()
+
+                               fout.write(text2save)
+                               fout.close()
+
+                               # ENV Varaiables info
+                               self.setenv_info()