added REMD/MREMD input generation in UNRESInpGen.py
[unres.git] / source / pymol / UNRESInpGen.py
1 # -*- coding: utf-8 -*-
2 '''
3 -------------------------------------------------------------------------------
4  UNRESInpGen.py - UNRES graphical input generator v 1.0
5 -------------------------------------------------------------------------------
6
7  Written by Dawid JagieÅ‚a (lightnir@chem.univ.gda.pl)  Oct 2012 
8
9 '''
10
11 from pymol import cmd,stored
12 from Tkinter import *
13 import tkFileDialog
14 import tkMessageBox 
15 import Pmw
16 import string
17 import os
18
19 UNRESInpGen_version="1.0"
20
21 def __init__(self):
22         self.UNRESInpGenWindow = None 
23         try:
24                 self.menuBar.addcascademenu('Plugin', 'UNRESPlugins', 'UNRESPACK Plugins', label='UNRES Plugins')
25         except:
26                 pass
27
28         self.menuBar.addmenuitem('UNRESPlugins', 'command','UNRESInpGen',
29                 label='UNRES Input Generator',
30                 command = lambda s=self: createUNRESInpGen(s) )
31
32 def createUNRESInpGen(app):
33         if (app.UNRESInpGenWindow == None):
34                 app.UNRESInpGenWindow = UNRESInpGenerator(app)
35         else:
36                 app.UNRESInpGenWindow.myToggle()        
37
38 #=================================================================
39
40
41 class UNRESInpGenerator(Toplevel):
42         global UNRESInpGen_version
43         # Class variables
44         """
45         cv = IntVar()
46         pp = IntVar()
47         cp = IntVar()
48         rv = IntVar()
49         colorize = IntVar()
50         """
51         seq_letter = IntVar()
52         writeSSbrige = IntVar()
53         OM1Val = StringVar()
54         OM2Val = StringVar()
55         CART = IntVar()
56         OVERLAP = IntVar()
57         NOSEARCHSC = IntVar()
58         objects_list = ['Select object']    
59         seq_list=[]
60         seq_length=0
61
62         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' ]
63
64         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',
65                                         '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'},
66                     {'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',
67                                         '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'},
68                     {'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',
69                                         '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'},
70                     {'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',
71                                         'WTURN3':'2.36351', 'WTURN4':'1.34051', 'WTURN6':'0.00000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
72                     {'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',
73                                         'WTURN3':'2.99827', 'WTURN4':'0.59174', 'WTURN6':'0.00000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
74                         {'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',
75                                         'WTURN3':'2.00764', 'WTURN4':'0.05345', 'WTURN6':'0.05282', 'WSCCOR':'0.0', 'CUTOFF': '7.00000', 'WCORR4':'0.00000' },
76                         {'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',
77                                         'WTURN4':'0.79171', 'WTURN6':'0.01074', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
78                         {'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',
79                                         'WTURN4':'4.35377', 'WTURN6':'0.10000', 'CUTOFF':'7.00000', 'WCORR4':'0.00000', 'WSCCOR':'0.00000'},
80                         {'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',
81                                         'WTURN4':'0.55588', 'WTURN6':'0.11539', 'CUTOFF':'7.00000', 'WCORR4':'0.0000', 'WTORD':'0.00000', 'WSCCOR':'0.00000'},
82                         {'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',
83                                         'WCORR6':'0.00000', 'SCAL14':'0.40000', 'SCALSCP':'1.00000', 'CUTOFF':'7.00000', 'WSCCOR':'0.00000'}
84         ]
85
86         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'}
87
88
89         def __init__(self,parent):
90                 # Create the GUI window 
91                 root = Toplevel.__init__(self)
92                 self.config(width=400, height=300)              # create a root window
93                 self.title("UNRES Input Generator v"+UNRESInpGen_version)                 # Set window title
94                 self.resizable(0, 0)                                # Disable window resize
95                 self.geometry('-40+40')                             # Set window placement
96
97                 # Create the Balloon.
98                 self.balloon = Pmw.Balloon(root)
99
100                 #================================ 
101                 # "Main Options" group 
102                 #
103                 self.gr1 = Pmw.Group(self,tag_text = 'Main options')
104                 self.gr1.grid(row=0, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
105
106                 # - Create title Entryfield & Label
107                 #self.l1 = Label(self.gr1.interior(), text="Title:")
108                 #self.l1.grid(row=0, column=0,sticky=E)
109                 self.e1 = Pmw.EntryField(self.gr1.interior(),
110                         labelpos='w',
111                         label_text="Title:",
112                         validate = {'max': 80 },
113                 #       value ="(Place input information here)"
114                 )
115                 self.e1.component('entry').config(width=80)
116                 self.e1.grid(row=0, column=0,columnspan=4, sticky=E)
117
118                 # - Create "choose method" OptionMenu
119                 self.OM1Val.set('MD')
120                 self.optmenu1 =  Pmw.OptionMenu(self.gr1.interior(),
121                         labelpos = 'w',
122                         label_text = 'Choose method:',
123                         menubutton_textvariable = self.OM1Val,
124                         items = ['MD', 'REMD/MREMD', 'MINIMIZE' ],
125                         command = self.switch_options,
126                         menubutton_width = 10
127                 )
128                 self.optmenu1.grid(row=1, column=0,columnspan=2, sticky=E)
129         
130
131                 # - Seed entryfield
132                 self.gr1.e1 = Pmw.EntryField(self.gr1.interior(),
133                         labelpos='w',
134                         label_text="Seed",
135                         validate = {'validator' : 'integer', 'min': -2147483648 , 'max' : 0 },
136                         value = "-1111333"
137                 )
138                 self.gr1.e1.component('entry').config(width=8)
139                 self.gr1.e1.grid(row=1, column=2, sticky=W)
140  
141                 #==================================
142                 # - MD options frame
143                 #
144                 self.gr1.md = Frame(self.gr1.interior())
145                 self.gr1.md.grid(row=2, column=0, columnspan=4,sticky=W+E)
146                 
147                 # -- nstep entryfield
148                 self.gr1.md.e1 = Pmw.EntryField(self.gr1.md,
149                         labelpos='w',
150                         label_text="NSTEP",
151                         validate = {'validator' : 'integer', 'min': 1 , 'max' : 1000000 },
152                         value = "500000"
153                 )
154                 self.balloon.bind(self.gr1.md.e1,'Number of calculation steps')
155                 self.gr1.md.e1.component('entry').config(width=8)
156                 self.gr1.md.e1.grid(row=0, column=0, sticky=E)
157
158                 # -- ntwe entryfield
159                 self.gr1.md.e2 = Pmw.EntryField(self.gr1.md,
160                         labelpos='w',
161                         label_text="NTWE",
162                         validate = {'validator' : 'integer', 'min': 0 , 'max' : 1000000 },
163                         value = "100"
164                 )
165                 self.balloon.bind(self.gr1.md.e2,'Frequency of energy output.\nNTWE=0 means no energy dump. ')
166                 self.gr1.md.e2.component('entry').config(width=8)
167                 self.gr1.md.e2.grid(row=0,column=1, sticky=E)
168
169                 # -- ntwx entryfield
170                 self.gr1.md.e3 = Pmw.EntryField(self.gr1.md,
171                         labelpos='w',
172                         label_text="NTWX",
173                         validate = {'validator' : 'integer', 'min': 1 , 'max' : 1000000 },
174                         value = "1000"
175                 )
176                 self.balloon.bind(self.gr1.md.e3, "Frequency of coordinate output.")
177                 self.gr1.md.e3.component('entry').config(width=8)
178                 self.gr1.md.e3.grid(row=0,column=2, sticky=E)
179
180                 # -- dt entryfield
181                 self.gr1.md.e4 = Pmw.EntryField(self.gr1.md,
182                         labelpos='w',
183                         label_text="DT",
184                         validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
185                         value = "0.1")
186                 self.balloon.bind(self.gr1.md.e4, "Time step. \nThe unit is \"molecular time unit\" (mtu)\n 1 mtu = 48.9 fs")
187                 self.gr1.md.e4.component('entry').config(width=8)
188                 self.gr1.md.e4.grid(row=0,column=3, sticky=E)
189
190                 # -- damax entryfield
191                 self.gr1.md.e5 = Pmw.EntryField(self.gr1.md,
192                         labelpos='w',
193                         label_text="DAMAX",
194                         validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
195                         value = "1.0")
196                 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.")
197                 self.gr1.md.e5.component('entry').config(width=8)
198                 self.gr1.md.e5.grid(row=1,column=0, sticky=E)
199
200                 # -- dvmax entryfield
201                 self.gr1.md.e6 = Pmw.EntryField(self.gr1.md,
202                         labelpos='w',
203                         label_text="DVMAX",
204                         validate = {'validator' : 'real', 'min': 0.001 , 'max' : 1000 },
205                         value = "20.0")
206                 self.balloon.bind(self.gr1.md.e6, "Maximum allowed velocity (in A/mtu).")
207                 self.gr1.md.e6.component('entry').config(width=8)
208                 self.gr1.md.e6.grid(row=1,column=1, sticky=E)
209
210                 # -- restet_vel entryfield
211                 self.gr1.md.e7 = Pmw.EntryField(self.gr1.md,
212                         labelpos='w',
213                         label_text="RESET_VEL",
214                         validate = {'validator' : 'integer', 'min': 0 , 'max' : 10000000 },
215                         value = "1000")
216                 self.balloon.bind(self.gr1.md.e7, "Frequency of resetting velocities to values from Gaussian distribution")
217                 self.gr1.md.e7.component('entry').config(width=8)
218                 self.gr1.md.e7.grid(row=1,column=2, sticky=E)
219                 
220                 # -- initial structure
221                 self.gr1.md.om1 = Pmw.OptionMenu(self.gr1.md,
222                         labelpos = 'w',
223                         label_text = 'Start from',
224                         items = ['PDB', 'extended', 'random' ],
225                         menubutton_width = 8,
226                 )
227                 self.gr1.md.om1.grid(row=1,column=3, sticky=E)
228
229                 #=================================
230                 #  - thermostat frame
231                 #
232                 self.gr1.th = Frame(self.gr1.interior())
233                 self.gr1.th.grid(row=3, column=0, columnspan=5,sticky=W+E)
234
235                 # -- Thermostat optionmenu 
236                 self.gr1.th.optmenu1 =  Pmw.OptionMenu(self.gr1.th,
237                         labelpos = 'w',
238                         label_text = 'thermostat',
239                         items = ['Berendsen', 'Nose-Poincare 1999','Nose-Poincare 2001', 'Nose-Hoover', 'Langevin' ],
240                         command=self.set_thermostat,
241                         menubutton_width = 15
242                 )
243                 self.gr1.th.optmenu1.pack(side=LEFT)#grid(row=0, column=0, sticky=E)
244
245                 # -- t_bath entryfield
246                 self.gr1.th.e1 = Pmw.EntryField(self.gr1.th,
247                         labelpos='w',
248                         label_text="T_BATH",
249                         validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 10000 },
250                         value = "300.0")
251                 self.balloon.bind(self.gr1.th.e1, "Temperature (in K) of canonical simulation.")
252                 self.gr1.th.e1.component('entry').config(width=8)
253                 self.gr1.th.e1.pack(side=LEFT)
254                 
255                 # -- tau_bath entryfield
256                 self.gr1.th.e2 = Pmw.EntryField(self.gr1.th,
257                         labelpos='w',
258                         label_text="TAU_BATH",
259                         validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 1000000 },
260                         value = "1.0")
261                 self.balloon.bind(self.gr1.th.e2, "(units are mtus; 1mtu=48.9 fs) \nConstant of the coupling to the thermal bath")
262                 self.gr1.th.e2.component('entry').config(width=8)
263                 self.gr1.th.e2.pack(side=LEFT)
264                                  
265                 # -- q_np entryfield
266                 self.gr1.th.e3 = Pmw.EntryField(self.gr1.th,   
267                         labelpos='w',
268                         label_text="Q_NP",
269                         validate = {'validator' : 'real', 'min': 0.000001 , 'max' : 1000000 },
270                         value = "0.1")
271                 self.balloon.bind(self.gr1.th.e3, "Mass of the fictitious particle in the calculations with the Nose-Poincare & Nose-Hoover thermostats.")
272                 self.gr1.th.e3.component('entry').config(width=8)
273                 #self.gr1.th.e2.pack(side=LEFT)
274
275                 
276                 #================================= 
277                 # - Minimization frame
278                 self.gr1.mi = Frame(self.gr1.interior())
279                 #self.gr1.mi.grid(row=4, column=0, columnspan=5,sticky=W+E)
280
281                 self.gr1.mi.e1 = Pmw.EntryField(self.gr1.mi,
282                         labelpos='w',
283                         label_text="MAXMIN",
284                         validate = {'validator' : 'integer', 'min': 0 , 'max' : 1000000 },
285                         value = "2000" )
286                 self.balloon.bind(self.gr1.mi.e1,'Maximum number of iterations of the SUMSL minimizer.')
287                 self.gr1.mi.e1.component('entry').config(width=8)
288                 self.gr1.mi.e1.pack(side=LEFT)
289
290                 self.gr1.mi.e2 = Pmw.EntryField(self.gr1.mi,
291                         labelpos='w',
292                         label_text="MAXFUN",
293                         validate = {'validator' : 'integer', 'min': 0 , 'max' : 1000000 },
294                         value = "5000" )
295                 self.balloon.bind(self.gr1.mi.e2,'Maximum number of function evaluations in a single minimization.')
296                 self.gr1.mi.e2.component('entry').config(width=8)
297                 self.gr1.mi.e2.pack(side=LEFT)
298
299                 self.gr1.mi.c1 = Checkbutton(self.gr1.mi,
300                         text = "CART",
301                         variable = self.CART )
302                 self.balloon.bind(self.gr1.mi.c1,'Minimize in virtual-bond vectors instead of angles.')
303                 self.gr1.mi.c1.pack(side=LEFT)
304
305                 self.gr1.mi.c2 = Checkbutton(self.gr1.mi,
306                         text = "OVERLAP",
307                         variable = self.OVERLAP )
308                 self.balloon.bind(self.gr1.mi.c2,'Fix overlaping sidechains.')
309                 self.gr1.mi.c2.pack(side=LEFT)
310
311                 self.gr1.mi.c3 = Checkbutton(self.gr1.mi,
312                         text = "NOSEARCHSC",
313                         variable = self.NOSEARCHSC )
314                 #self.balloon.bind(self.gr1.mi.c3,'Minimize in virtual-bond vectors instead of angles.')
315                 self.gr1.mi.c3.pack(side=LEFT)
316
317
318                 #=================================
319                 # - REMD frame
320                 self.gr1.re = Frame(self.gr1.interior())
321                 #self.gr1.re.grid(row=5, column=0, columnspan=5,sticky=W+E)
322
323                 self.gr1.re.e1 = Pmw.EntryField(self.gr1.re,
324                         labelpos = 'w',
325                         label_text = "NREP",
326                         validate = {'validator' : 'integer', 'min': 1 , 'max' : 32 },
327                         command = self.set_replica_widgets,
328                         value = "16" )
329                 self.balloon.bind(self.gr1.re.e1,'Number of replicas in a REMD/MREMD run.')
330                 self.gr1.re.e1.component('entry').config(width=8)
331                 self.gr1.re.e1.grid(row=0, column=0, sticky=W)
332                 
333                 self.gr1.re.e2 = Pmw.EntryField(self.gr1.re,
334                         labelpos = 'w',
335                         label_text = "NSTEX",
336                         validate = {'validator' : 'integer', 'min': 0 , 'max' : 1000000 },
337                         value = "1000" )
338                 self.balloon.bind(self.gr1.re.e2,'Number of steps after which exchange is performed in REMD/MREMD runs.')
339                 self.gr1.re.e2.component('entry').config(width=8)
340                 self.gr1.re.e2.grid(row=0, column=1, sticky=W)
341
342                 # -- radio select
343                 self.gr1.re.rs = Pmw.RadioSelect(self.gr1.re,
344                         labelpos = 'w',
345                         label_text = 'Replica temperatures',
346                         command = self.sel_replica_mode,
347                         buttontype = 'radiobutton'
348                         #frame_borderwidth = 2,
349                         #frame_relief = 'ridge' 
350                         )
351                 self.gr1.re.rs.grid(row=1, column=0, columnspan=4,sticky=W)
352
353                 for text in ('Manual', 'Range'):
354                         self.gr1.re.rs.add(text)
355                 
356                 # --- range
357                 self.gr1.re.tf1 = Frame(self.gr1.re, bg="blue")
358                 self.gr1.re.tf1.grid(row=2,column=0, columnspan=4, sticky=W)
359
360                 self.gr1.re.tf1.e1 = Pmw.EntryField(self.gr1.re.tf1,
361                         labelpos = 'w',
362                         label_text = "RETMIN",
363                         validate = {'validator' : 'real', 'min': 0 , 'max' : 1000000 },
364                         value = "10" )
365                 self.balloon.bind(self.gr1.re.tf1.e1,'Minimum temperature in a REMD/MREMD run.')
366                 self.gr1.re.tf1.e1.component('entry').config(width=8)
367                 self.gr1.re.tf1.e1.grid(row=0, column=0, sticky=W)
368
369                 self.gr1.re.tf1.e2 = Pmw.EntryField(self.gr1.re.tf1,
370                         labelpos = 'w',
371                         label_text = "RETMAX",
372                         validate = {'validator' : 'real', 'min': 0 , 'max' : 1000000 },
373                         value = "1000" )
374                 self.balloon.bind(self.gr1.re.tf1.e2,'Maxmum temperature in a REMD/MREMD run.')
375                 self.gr1.re.tf1.e2.component('entry').config(width=8)
376                 self.gr1.re.tf1.e2.grid(row=0, column=1, sticky=W)
377                 
378                 # --- manual
379                 self.gr1.re.tf2 = Frame(self.gr1.re) 
380                 self.gr1.re.tf2.grid(row=3,column=0, columnspan=4, sticky=W)
381
382                 self.gr1.re.tf2.te = []
383                 for i in range(0,32): #int(self.gr1.re.e1.get())):
384                         self.gr1.re.tf2.te.append(Pmw.EntryField(self.gr1.re.tf2,
385                                 labelpos='n',
386                                 label_text='T%02d' % (i+1),
387                                 validate = {'validator' : 'real','min' : 0, 'max' : 1000, 'minstrict' : 0},
388                                 value = '%d' % (200+i*10)))
389                         self.gr1.re.tf2.te[i].component('entry').config(width=3)
390                         self.gr1.re.tf2.te[i].grid(row=1+(i//16), column=0+(i % 16))
391
392                 self.gr1.re.tf2.nre = Pmw.EntryField(self.gr1.re.tf2, 
393                         labelpos ='n',
394                         label_text='Rep. in Temp.',
395                         validate = {'validator' : 'integer','min' : 1, 'max' : 100 },
396                         value = '2')
397                 self.gr1.re.tf2.nre.component('entry').config(width=3)
398                 self.gr1.re.tf2.nre.grid(row=1, column=17)
399
400                 # display manual replica options 
401                 self.gr1.re.e1.invoke()
402                 self.gr1.re.rs.invoke('Manual')
403
404                 #================================= 
405                 # "Force field options" group
406                 #     
407                 self.gr2 = Pmw.Group(self,tag_text = 'Force field options')
408                 self.gr2.grid(row=2, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
409
410                 # - Create "force field parameters" Option menu
411                 self.OM2Val.set('Custom')
412                 self.optmenu2 = Pmw.OptionMenu(self.gr2.interior(),
413                 label_text = 'Force field parameters:',
414                         labelpos = 'w',
415                         menubutton_textvariable = self.OM2Val,
416                         items = ['Custom','GAB','E0G', '1L2Y_1LE1','4P','3P','CASP5','ALPHABETA','BETA','ALPHA','CASP3' ],
417                         initialitem = 'Custom',
418                         menubutton_width = 10,
419                         command=self.set_force_field
420                 )
421                 self.optmenu2.grid(row=0, column=0,columnspan=4,sticky=E)
422
423                 # Force field parameters Entry Fields   
424                 self.ef = []
425                 for i in range(0,len(self.weights)):
426                         self.ef.append(Pmw.EntryField(self.gr2.interior(), 
427                         labelpos='n',
428                         label_text=self.weights[i],
429                         validate = {'validator' : 'real','min' : 0, 'max' : 10, 'minstrict' : 0},
430                         value = '1.00000'))
431                         self.ef[i].component('entry').config(width=8)
432                         self.ef[i].grid(row=1+(i//9), column=0+(i % 9))
433                 
434                 #===================================
435                 # "Sequence" group 
436                 #
437                 self.gr3 = Pmw.Group(self,tag_text = 'Sequence')
438                 self.gr3.grid(row=3, column=0,columnspan=4,sticky=W+E,padx=10, pady=5)
439                                 
440                 self.gr3.f1 = Frame(self.gr3.interior())
441                 # Object List  
442                 self.cb2 = Pmw.ComboBox(self.gr3.f1,
443                         labelpos = 'w',
444                         #entry_relief = 'raised',
445                         label_text = 'Selection/Object',
446                         scrolledlist_items = self.objects_list
447                 )
448                 self.cb2.pack(side=LEFT)
449                 # refresh button
450                 self.gr3.btn1 = Button(self.gr3.f1, text='Refresh', padx=0, pady=0 , command = self.refresh_list)
451                 self.gr3.btn1.pack(side=LEFT)  
452                 # Get sequence button 
453                 self.gr3.btn2 = Button(self.gr3.f1, text='Get Sequence', padx=0, pady=0 , command = self.get_seq)
454                 self.gr3.btn2.pack(side=LEFT)  
455                         
456                 self.gr3.f1.pack(expand="yes",fill="both")
457
458                 # Disulfide brige checkbox
459                 self.gr3.chk = Checkbutton(self.gr3.f1, text="Write disulfide bridges", variable=self.writeSSbrige)
460                 self.gr3.chk.pack(side=LEFT)
461
462                 # Sequence text
463                 self.gr3.t1 = Pmw.ScrolledText(self.gr3.interior(),
464                         columnheader = 1,
465                         columnheader_width = 3,
466                         rowheader = 1,
467                         rowheader_width = 4,
468                         usehullsize=1,
469                         hull_width=30,
470                         hull_height=180,
471                         text_padx = 4,
472                         text_pady = 4,
473                         Header_padx = 4,
474                         rowheader_pady = 4,
475                 )
476                 # Sequence text - create the header line 
477                 headerline = ''
478                 for column in range(1,21):
479                         headerline = headerline + ('%-4s' % str(column) )
480                 self.gr3.t1.component('columnheader').insert('0.0',headerline)
481
482                 self.gr3.t1.pack(expand="yes",fill="both") 
483
484                 # Add some buttons
485                 btn3=Button(self, text='Write Input', padx=0, pady=0, command = self.ok)
486                 btn3.grid(row=10, column=0, columnspan=2,sticky=N+W+S+E)
487                 btn4=Button(self, text='Close', padx=0, pady=0, command = self.myHide)
488                 btn4.grid(row=10, column=2, columnspan=2,sticky=N+W+S+E)
489
490                 # create callback to prevent window kill
491                 self.protocol("WM_DELETE_WINDOW", self.myHide)
492
493         def ToggleColor(self):
494                 if self.colorize.get()==1:
495                         for i in range(0,len(self.res_states)):
496                                 UNRESInpGenWindow.ccb[i].config(state=ACTIVE, bg=self.res_states[i][1], activebackground=self.res_states[i][1], relief=RAISED, overrelief=RAISED)
497                 else:
498                         for i in range(0,len(self.res_states)):
499                                 UNRESInpGenWindow.ccb[i].config(state=DISABLED, bg=self.Default_Color , activebackground=self.Default_Color, relief=RAISED, overrelief=RAISED)
500
501         def myShow(self):
502                 self.deiconify()
503
504         def myHide(self):
505                 self.withdraw()
506
507         def myToggle(self):
508                 if self.state() == "normal":
509                         self.myHide()
510                 elif self.state() == "withdrawn":
511                         self.myShow()
512         
513         def get_selections(self):
514                 self.objects_list = []
515                 for item in cmd.get_names("all"):
516                         if cmd.get_type(item)=="object:molecule":
517                                 self.objects_list.append(item)
518                         if cmd.get_type(item)=="selection":
519                                 if item[0]<>"_":
520                                         self.objects_list.append(item)
521
522         def get_nonstandard(self):
523                 stored.list=[]
524                 cmd.iterate("(all)","stored.list.append(resn)")
525                 stored.list=list(Set(stored.list))  # remove duplicates
526                 # Remove standard amino acids and water from list
527                 for m in ['HIS','ASP','ARG','PHE','ALA','CYS','GLY','GLN','GLU','LYS','LEU','MET','ASN','SER','TYR','THR','ILE','TRP','PRO','VAL','HOH']:
528                         try:
529                                 stored.list.remove(m)
530                         except ValueError:
531                                 pass
532                 UNRESInpGenWindow.cbcr1.setlist(stored.list)
533
534         def refresh_list(self):
535                 # Save old values
536                 old = self.objects_list
537                 try:
538                         old_cb2=self.cb2.getvalue()[0]
539                 except:
540                         old_cb2=''
541                 self.get_selections()
542
543                 # Update selectionlist if needed
544                 if not(old==self.objects_list):
545                         self.cb2.setlist(self.objects_list)
546                         self.cb2.setlist(self.objects_list)
547
548                 if not(old_cb2 in self.objects_list):
549                         # No - clear the combobox entry
550                         self.cb2.component('entryfield').clear()
551                 else:
552                         # Yes - set the old value
553                         self.cb2.selectitem(old_cb2,setentry=1)
554         
555         
556         def get_seq(self):
557                 # Get the number of chains 
558                 try: 
559                         nchains=int(len(cmd.get_chains(self.cb2.getvalue()[0])))
560                 except:
561                         nchains=0
562                 pass
563                 
564                 if (nchains>0):
565                         self.seq_list=[]
566                 offset=0
567                 seq_data=''
568                 self.seq_length=0
569                 for chain in range(0,nchains):
570                         # Get only amonoacids, N-terminus acyl and C-terminus amide
571                         # example:      (1uRC and chain F and (n. ca or (resn ACE and n. C) or (resn NH2 and n. N)))
572                         # No chain information or only one chain
573                         if nchains==1:
574                                 atomchain=cmd.get_model(str(self.cb2.getvalue()[0])+" & (n. ca|(resn ACE & n. C)|(resn NH2+NHH+NME & n. N))").atom
575                         # Chain information is present
576                         else:
577                                 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
578                         # dodaj separator lancuchow
579                         if chain>0:
580                                 self.seq_list.append("D  ")
581                                 self.seq_length+=1
582                                 
583
584                         # Zamiana chronionych
585                         # ACE ALA ALA NH2 D   ACE ALA ALA NH2
586                         # GLY ALA ALA GLY D   GLY ALA ALA GLY
587                         # Zamiana niechronionych 
588                         #     ALA ALA     D       ALA ALA
589                         # D   ALA ALA     D       ALA ALA D
590                         #
591                         # j - licznik pozycji reszty
592                         j=0
593                         for i in atomchain:
594                                 self.seq_length+=1
595                                 if str(i.resn)=="NH2":
596                                         self.seq_list.append("GLY")
597                                 elif str(i.resn)=="NHH":
598                                         self.seq_list.append("GLY")
599                                 elif str(i.resn)=="NME":
600                                         self.seq_list.append("GLY")
601                                 elif str(i.resn)=="ACE":
602                                         self.seq_list.append("GLY")
603                                 elif str(i.resn)=="GLY":
604                                         self.seq_list.append("GLY")
605                                 else:
606                                         if j==0 and chain==0: 
607                                                 self.seq_list.append("D  ")     
608                                                 self.seq_list.append(str(i.resn))
609                                                 self.seq_length+=1
610                                         elif j==len(atomchain)-1 and chain==(nchains-1):
611                                                 self.seq_list.append(str(i.resn))
612                                                 self.seq_list.append("D  ")
613                                                 self.seq_length+=1
614                                         else:
615                                                 self.seq_list.append(str(i.resn))
616                                 j+=1
617                 rows=0
618                 #row_header='0'  - old header
619                 row_header='1'
620                 # tag setup 
621                 self.gr3.t1.tag_configure('dummy', background = 'LightBlue1')
622                 tagList=[]
623                 self.gr3.t1.tag_configure('cysteine', background = 'LightGoldenrod1')
624                 CysTagList=[]
625
626                 for i in range(len(self.seq_list)):
627                         # Dummy tag
628                         if self.seq_list[i]=="D  ":
629                                 tag1 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80))
630                                 tag2 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80)+3)
631                                 tagList.append(tag1)
632                                 tagList.append(tag2)
633                         # Cysteine tag  
634                         if self.seq_list[i]=="CYS" or self.seq_list[i]=="CYX":
635                                 tag1 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80))
636                                 tag2 = '%d.%d' % (rows+1, ((len(seq_data)-rows)%80)+3)
637                                 CysTagList.append(tag1)
638                                 CysTagList.append(tag2)
639                         #       
640                         offset+=1
641                         seq_data=seq_data+self.seq_list[i]+" "
642                         # Line Wrap
643                         if offset>19:
644                                 offset=0
645                                 seq_data=seq_data+'\n'
646                                 rows+=1
647                                 #row_header=row_header+'\n'+str(rows*20)    - old header
648                                 row_header=row_header+'\n'+str(rows+1)
649
650                 self.gr3.t1.clear()
651                 self.gr3.t1.insert('end',seq_data)
652                 # Apply tags
653                 if len(tagList): 
654                         apply(self.gr3.t1.tag_add, ('dummy',) + tuple(tagList))
655                 if len(CysTagList):
656                         apply(self.gr3.t1.tag_add, ('cysteine',) + tuple(CysTagList))
657
658                 # Show row header
659                 self.gr3.t1.component('rowheader').delete(1.0, END)
660                 self.gr3.t1.component('rowheader').insert('end',row_header)     
661
662     
663         def switch_options(self,calctype):
664                 '''
665                         Displays the options available to set depending on the currently 
666                         selected calculation type
667                 '''
668                 # Hide all
669                 self.gr1.th.grid_remove()
670                 self.gr1.md.grid_remove()
671                 self.gr1.mi.grid_remove()
672                 self.gr1.re.grid_remove()
673                 # Show MD stuff
674                 if  self.OM1Val.get()=="MD":
675                         self.gr1.md.grid(row=2, column=0, columnspan=5, sticky=W+E)
676                         self.gr1.th.grid(row=3, column=0, columnspan=5, sticky=W+E)
677                 elif self.OM1Val.get()=="REMD/MREMD":
678                         self.gr1.md.grid(row=2, column=0, columnspan=5, sticky=W+E)
679                         self.gr1.th.grid(row=3, column=0, columnspan=5, sticky=W+E)
680                         self.gr1.re.grid(row=5, column=0, columnspan=5, sticky=W+E)
681                 elif self.OM1Val.get()=="MINIMIZE":
682                         self.gr1.mi.grid(row=4,column=0,columnspan=5, sticky=W+E)
683
684         def sel_replica_mode(self,mode):
685                 '''
686                         Display replica temperatures settings
687                 '''
688                 try:
689                         self.gr1.re.tf1.grid_remove()
690                         self.gr1.re.tf2.grid_remove()
691                         if mode=="Range":
692                                 self.gr1.re.tf1.grid(row=2,column=0, columnspan=4, sticky=W)    
693                         elif mode=="Manual":
694                                 self.gr1.re.tf2.grid(row=3,column=0, columnspan=4, sticky=W)
695                 except:
696                         pass
697
698         def set_replica_widgets(self):
699                 '''
700                         Refresh list of available temperature widgets in manual mode
701                 '''
702                 #print self.gr1.re.e1.get()
703                 for i in range(0,32): #int(self.gr1.re.e1.get())):
704                         try:
705                                 if i<int(self.gr1.re.e1.get()):
706                                         self.gr1.re.tf2.te[i].component('entry').config(state=NORMAL)
707                                 else:
708                                         self.gr1.re.tf2.te[i].component('entry').config(state=DISABLED)
709                         except:
710                                 pass
711
712
713
714         def set_force_field(self, pole):
715                 '''
716                         Enables/disables entryfields for force field perameters depending
717                         on the currently selected force field 
718                 '''
719                 for ff in self.force_fields:
720                         if ff['FF']==pole: 
721                                 #print ff
722                                 for i in range(0,len(self.weights)):
723                                         if ff.has_key(self.weights[i]):
724                                                 self.ef[i].setvalue(ff.get(self.weights[i]))
725                                                 self.ef[i].component('entry').config(state=NORMAL)
726                                         else:
727                                                 self.ef[i].component('entry').config(state=DISABLED)
728                         # Custom force field
729                         elif pole=='Custom':
730                                 for i in range(0,len(self.weights)):
731                                         self.ef[i].component('entry').config(state=NORMAL)
732
733         def set_thermostat(self,thermostat):
734                 '''
735                         Display additional widget acording to selected thermostat
736                 '''
737                 #print thermostat
738                 self.gr1.th.e2.pack_forget()
739                 self.gr1.th.e3.pack_forget()
740                 if thermostat=='Berendsen':
741                         self.gr1.th.e2.pack(side=LEFT)
742                 elif thermostat=='Nose-Poincare 1999' or thermostat=='Nose-Poincare 2001' or thermostat=='Nose-Hoover':
743                         self.gr1.th.e3.pack(side=LEFT)
744
745         def fortran_format(self,s):
746                 '''
747                     Formats string containing keywords to wrap over 80 columns.
748                         Input string should be one line.
749                 '''
750                 tmpstr=''
751                 column=1
752                 for k in s.split():
753                         if column+len(k)+1<80:
754                                 tmpstr+=k+' '
755                                 column+=len(k)+1
756                         else:
757                                 tmpstr+=" "*(80-column)+"&\n"+k+" "
758                                 column=len(k)+2
759                 tmpstr+='\n'
760                 return tmpstr
761
762         def get_weights(self):
763                 '''
764                         Get the force field weights
765                 '''
766                 s = ''
767                 for i in range(0,len(self.weights)):
768                         if self.ef[i].component('entry').cget("state")=="normal":
769                                 s+=self.weights[i]+"="+self.ef[i].getvalue()+" "
770                 return s
771
772         def get_md_opt(self):
773                 '''
774                         Get MD options for main input
775                 '''
776                 s = "NSTEP="+self.gr1.md.e1.getvalue()+" NTWE="+self.gr1.md.e2.getvalue()+" "
777                 s+= "NTWX="+self.gr1.md.e3.getvalue()+" DT="+self.gr1.md.e4.getvalue()+" "
778                 s+= "DAMAX="+self.gr1.md.e5.getvalue()+" DVMAX="+self.gr1.md.e6.getvalue()+" " 
779                 s+= "RESET_VEL="+self.gr1.md.e7.getvalue()+" " 
780                 
781                 # Thermostat options
782                 term=self.gr1.th.optmenu1.getvalue()
783                 #print term
784                 if term=="Berendsen":
785                         s+="TBF TAU_BATH="+self.gr1.th.e2.getvalue()+" "
786                 elif term=="Nose-Poincare 1999":
787                         s+="NOSEPOINCARE99 Q_NP="+self.gr1.th.e3.getvalue()+" "
788                 elif term=="Nose-Poincare 2001":
789                         s+="NOSEPOINCARE01 Q_NP="+self.gr1.th.e3.getvalue()+" "
790                 elif term=="Nose-Hoover":
791                         s+="NOSEHOOVER96 Q_NP="+self.gr1.th.e3.getvalue()+" "
792                 elif term=="Langevin":
793                         s+="LANG=1 "
794
795                 s+="T_BATH="+self.gr1.th.e1.getvalue()+" "
796                 return s
797
798         def get_minim_opt(self):
799                 '''
800                         Get minimization options
801                 '''
802                 s = "MAXMIN="+self.gr1.mi.e1.getvalue()+" MAXFUN="+self.gr1.mi.e2.getvalue()
803                 return s
804
805
806         def get_mremd_opt(self):
807                 '''
808                         Generates a sting containing REMD?MREMD main options for input
809                 '''
810                 s = "NREP="+self.gr1.re.e1.get()+" NSTEX="+self.gr1.re.e2.get()+" "
811                 if self.gr1.re.rs.getvalue()=="Range":
812                         s+="RETMIN="+self.gr1.re.tf1.e1.get()+"RETMAX="+self.gr1.re.tf1.e2.get()
813                 else:
814                         s+="TLIST MLIST" 
815                 s+=" TRAJ1FILE REST1FILE SYNC"
816
817                 return s
818
819         def get_mremd_temp_opt(self):
820                 '''
821                         Generate a strong containing temperatures for REMD/MREMD "manual mode"
822                 '''
823                 s=""
824                 for i in range(0,int(self.gr1.re.e1.get())):
825                         s+=self.gr1.re.tf2.te[i].get()+" "      
826
827                 return s
828
829         def get_mremd_replicas(self):
830                 '''
831                         Generates a string containing number of replicas in every temperature for REMD/MREMD calculations.
832                         For REMD calculations contains only sequence of ones.
833                 '''
834                 s=""
835                 for i in range(0,int(self.gr1.re.e1.get())):
836                         s+=self.gr1.re.tf2.nre.get()+" "
837                 return s
838
839
840         def get_seq_data(self):
841                 '''
842                         Dumps the sequence and disulfide bridge information
843                 '''
844                 # write sequence length 
845                 s = str(self.seq_length)+"\n"
846
847                 chains=cmd.get_chains(self.cb2.getvalue()[0])
848                 nchains=len(chains)
849
850                 # apply one space before each sequence line 
851                 seq=self.gr3.t1.get()
852                 for line in seq.split('\n'):
853                         s+=" "+line+"\n"
854                 # remove last newline character
855                 s = s[:-1]
856
857                 # disulfide bridges - get half-cysteines by selection:
858         # sele (bto. ((object) & r. CYS+CYX & n. SG) )& n. SG
859                 ncys=cmd.get_model("(bto. (("+str(self.cb2.getvalue()[0])+") & r. CYS+CYX & n. SG)) & n. SG").atom
860                 nSSbr=len(ncys)/2
861         
862                 
863                 # Is "Write disulfide brige" checked?
864                 # yes
865                 if self.writeSSbrige.get():
866                         # write number of half-cysteines
867                         s+=str(len(ncys))+"\n"
868                         if len(ncys)==0:
869                                 # No half-cysteines, cys position = 0  
870                                 s+=" 0\n"
871                         else:
872                                 # Write half-cysteine positions in sequence
873                                 #       
874                                 # get first chain
875                                 first=cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+str(chains[0])+" & n. ca")
876                         
877                                 # calculate base offset in first chain (if dummy atom present offset = 1 )      
878                                 if first.atom[0].resn=="GLY":
879                                         boff=0
880                                 else: 
881                                         boff=1 
882                         
883                                 # create dictionary of PDB chain/resi to UNRES_index
884                                 unresidx={}
885                                 for c in ncys:
886                                         # calculate residue index offset from first residue in chain containing half-cysteine
887                                         fresinchain=cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+c.chain+" & n. ca").atom
888                                         roff=int(c.resi)-int(fresinchain[0].resi)+1
889                                 
890                                         resb=0
891                                         coff=0
892                                         for r in chains:
893                                                 if c.chain==r:
894                                                         break
895                                                 resb+=len(cmd.get_model(str(self.cb2.getvalue()[0])+"& chain "+r+" & n. ca").atom)
896                                                 coff+=1
897                                         # add key/value to dictionary
898                                         unresidx[c.chain+"/"+str(c.resi)]=boff+resb+coff+roff   
899                                         s+=" "+str(boff+resb+coff+roff)
900                                 s+="\n"
901
902                                 # Write the number of disulfide bridges
903                                 s+=" "+str(nSSbr)+"\n"
904                         
905                                 lista_mostkow=[]
906                                 for c in ncys:
907                                         # get neibhoring Sulfur atom
908                                         opis=c.chain+str(c.resi)
909                                         lista_mostkow.append(opis)
910                                         nbr=cmd.get_model("(bto. ("+str(self.cb2.getvalue()[0])+" & resi "+str(c.resi)+"& n. SG & chain "+str(c.chain)+")) & n. SG").atom[0]
911                                         opis2=nbr.chain+str(nbr.resi)
912                                         if opis2 not in lista_mostkow:
913                                                 # Write witch half-cysteines build the i-th disulfide bridge
914                                                 s+=" "+str(unresidx[c.chain+"/"+str(c.resi)])+" "+str(unresidx[nbr.chain+"/"+str(nbr.resi)])+"\n"
915                                                 #print c.chain, c.resn,c.resi,"-S-S-", nbr.chain, nbr.resn,nbr.resi
916                 # Don't writeSSbrige    
917                 else:
918                         s+="0\n 0\n"
919
920                 return s
921
922
923         def write_cshell(self, cshname,prefix):
924                 '''
925                         Writes the C-shell script needed to run UNRES calculations
926                 '''
927                 s='#!/bin/csh -f\n#\n# C-shell script generated by UNRESInpGen.py\n#\n'
928                 
929                 # number of processors per energy
930                 if self.OM1Val.get()=="MD":
931                         s+='setenv FGPROCS 1\n'
932
933                 # Potential
934                 if self.OM2Val.get()=="CASP3":
935                         s+='setenv POT LJ\n'
936                 else:
937                         s+='setenv POT GB\n'
938
939                 # input file
940                 s+='setenv PREFIX '+prefix+'\n'
941
942                 # Parallel stuff
943                 s+='setenv OUT1FILE YES\n'
944
945                 # force filed parameters
946                 s+='#---------------------------------------------------------------------\n'
947                 s+='setenv DD $UNRES_ROOT/PARAM\n'
948
949                 if self.OM2Val.get()=="CASP3":
950                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
951                         s+='setenv TORPAR $DD/torsion_cryst.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_LJ.parm\n'
952                         s+='setenv ELEPAR $DD/electr.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_GAP.parm\n'
953                         s+='setenv SCCORPAR $DD/rotcorr_AM1.parm\n'
954                 elif self.OM2Val.get()=="ALPHA" or self.OM2Val.get()=="BETA" or self.OM2Val.get()=="ALPHABETA":
955                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
956                         s+='setenv TORPAR $DD/torsion_ecepp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_GB.parm\n'
957                         s+='setenv ELEPAR $DD/electr.parm\nsetenv SCPPAR $DD/scp.parm\nsetenv FOURIER $DD/fourier_GAP.parm\nsetenv SCCORPAR $DD/rotcorr_AM1.parm\n'
958                 elif self.OM2Val.get()=="CASP5":
959                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
960                         s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_GB.parm\n'
961                         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'
962                 elif self.OM2Val.get()=="3P":
963                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
964                         s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.3P7_iter81_1r\n'
965                         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'
966                 elif self.OM2Val.get()=="4P":
967                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
968                         s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/sc_GB_opt.4P5_iter33_3r\n'
969                         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'
970                 elif self.OM2Val.get()=="GAB":
971                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
972                         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'
973                         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'
974                 elif self.OM2Val.get()=="E0G":  
975                         s+='setenv BONDPAR $DD/bond.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/scgauss.parm\n'
976                         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'
977                         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'
978                 elif self.OM2Val.get()=="1L2Y_1LE1":
979                         s+='setenv BONDPAR $DD/bond_AM1.parm\nsetenv THETPAR $DD/thetaml.5parm\nsetenv ROTPAR $DD/rotamers_AM1_aura.10022007.parm\n'
980                         s+='setenv TORPAR $DD/torsion_631Gdp.parm\nsetenv TORDPAR $DD/torsion_double_631Gdp.parm\nsetenv SIDEPAR $DD/scinter_$POT.parm\n'
981                         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'
982                 elif self.OM2Val.get()=="Custom":
983                         s+='setenv BONDPAR $DD/.parm\nsetenv THETPAR $DD/.parm\nsetenv ROTPAR $DD/.parm\n'
984                         s+='setenv TORPAR $DD/.parm\nsetenv TORDPAR $DD/.parm\nsetenv SIDEPAR $DD/.parm\n'
985                         s+='setenv ELEPAR $DD/.parm\nsetenv SCPPAR $DD/.parm\nsetenv FOURIER $DD/.parm\nsetenv SCCORPAR $DD/.parm\n'
986
987
988
989                 s+='setenv PATTERN $DD/patterns.cart\n'
990                 s+='#---------------------------------------------------------------------\n'
991                 s+='$UNRES_BIN $*\n'
992
993                 f = open(cshname, 'w')
994                 f.write(s)
995                 f.close()
996
997
998         def setenv_info(self):
999                 print '''IMPORTANT: Remember to set the following envirament variables for your shell before starting calculations:
1000                   UNRES_ROOT - the root directory where UNRES is installed on your system (should contain PARAM directory)
1001                   UNRES_BIN  - the UNRES binary you want to execute
1002                 '''
1003
1004
1005         def ok(self):
1006                 '''
1007                     Writes the actual input     
1008                 '''
1009                 myFormats = [
1010                     ('Input files','*.inp'),
1011                         ('All files','*.*')
1012                 ]
1013                 # Write error handling for empty sequence
1014                 #
1015                 s=self.gr3.t1.getvalue()
1016                 if len(s.strip())==0:
1017                         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\".")
1018                 else:                           
1019                         # Display dialog window
1020                         fout = tkFileDialog.asksaveasfile(parent=self,mode='w',filetypes=myFormats,title='Save input')
1021                         if fout:
1022                                 print "Saving input file %s" % fout.name
1023                                 # Get input header
1024                                 text2save=self.fortran_format(self.e1.get())
1025                                 # Get main options
1026                                 mainopt="SEED="+self.gr1.e1.get()+" "
1027                                 if self.OM1Val.get()=="MD":
1028                                         mainopt+="MD PDBREF"
1029                                         if self.gr1.md.om1.getvalue()=="PDB":
1030                                                 mainopt+=" PDBSTART"
1031                                         elif self.gr1.md.om1.getvalue()=="extended":
1032                                                 mainopt+=" EXTCONF"
1033                                         else:
1034                                                 mainopt+=" RAND_CONF"
1035                                 elif self.OM1Val.get()=="REMD/MREMD":
1036                                         mainopt+="RE PDBREF"
1037                                         if self.gr1.md.om1.getvalue()=="PDB":
1038                                                 mainopt+=" PDBSTART"
1039                                         elif self.gr1.md.om1.getvalue()=="extended":
1040                                                 mainopt+=" EXTCONF"
1041                                         else:
1042                                                 mainopt+=" RAND_CONF"
1043                                 
1044                                 elif self.OM1Val.get()=="MINIMIZE":
1045                                         mainopt+="PDBREF PDBSTART MINIMIZE RESCALE_MODE=0"
1046                                         if self.CART.get():
1047                                                 mainopt+=" CART"
1048                                         if self.OVERLAP.get():
1049                                                 mainopt+=" OVERLAP"
1050                                         if self.NOSEARCHSC.get():
1051                                                 mainopt+=" NOSERARCHSC"
1052                                 text2save+=self.fortran_format(mainopt)
1053                                 # Get aux options
1054
1055                                 if self.OM1Val.get()=="MD":
1056                                         text2save+=self.fortran_format(self.get_md_opt())
1057                                 elif self.OM1Val.get()=="REMD/MREMD":
1058                                         text2save+=self.fortran_format(self.get_md_opt())
1059                                         text2save+=self.fortran_format(self.get_mremd_opt())
1060                                         text2save+=self.fortran_format(self.get_mremd_temp_opt())
1061                                         text2save+=self.fortran_format(self.get_mremd_replicas())
1062                                 elif self.OM1Val.get()=="MINIMIZE":
1063                                         text2save+=self.fortran_format(self.get_minim_opt())
1064
1065                                 # Get force fields parameters
1066                                 text2save+=self.fortran_format(self.get_weights())
1067                 
1068                                 # PDB reference
1069                                 pdbreffn=str(self.cb2.getvalue()[0])+"_pdbref.pdb"
1070                                 text2save+=pdbreffn+"\n"
1071                                 print "Saving PDB reference structure %s" % (os.path.join(os.path.dirname(fout.name),pdbreffn))
1072                                 cmd.save(os.path.join(os.path.dirname(fout.name),pdbreffn), self.cb2.getvalue()[0])
1073
1074                                 # C-shell script 
1075                                 cshellfn=os.path.join(os.path.dirname(fout.name),"unres_"+os.path.basename(os.path.splitext(fout.name)[0])+".csh")
1076                                 print "Writing C-shell script %s" % (cshellfn)
1077                                 prefix=os.path.basename(os.path.splitext(fout.name)[0])
1078                                 self.write_cshell(cshellfn,prefix)
1079                                 
1080                                 # Get sequence data
1081                                 text2save+=self.get_seq_data()
1082
1083                                 fout.write(text2save)
1084                                 fout.close()
1085
1086                                 # ENV Varaiables info
1087                                 self.setenv_info()