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