16d942abe437ecf39480a87b5d8c6fcccc601ac4
[django_unres.git] / django_simple / todo / forms.py
1 from django import forms
2 from .models import Task
3 from .models import MIN_CHOICE
4 from .models import MD_START
5 from .models import MD_LANG
6 from .models import FF_CHOICE
7 import json
8 import urllib
9
10 def pdb_missing_res(file):
11    msg=''
12    newchain = True
13    ires=[]
14    for line in file:
15       if line[0:6] == 'ATOM  ' and line[13:15] == 'CA':
16                i = int(line[22:26])
17                if ires and i==ires[-1]:
18                  continue
19                if newchain or i==ires[-1]+1:
20                  ires.append(i)
21                  newchain = False
22                else:
23                  msg = 'chain breaks between residues '+\
24                    str(ires[-1])+' and '+str(i)+\
25                    ', server cannot add missing residues to PDB file - please repair the structure using e.g. Modeller'
26                  break
27       if line[0:3] == 'TER':
28                newchain = True
29       if line[0:3] == 'END':
30                break
31    
32    return(msg)
33
34 class MultiWidgetBasic(forms.MultiWidget):
35     def __init__(self, count, attrs=None):
36         self.count=count
37         widgets = []
38         for i in range(self.count):
39            widgets.append(forms.TextInput())
40         super(MultiWidgetBasic, self).__init__(widgets, attrs)
41
42     template_name = 'multi.html'
43
44     def decompress(self, value):
45         if value:
46             return json.loads(value)
47         else:
48             return ['', '']
49
50
51 class MultiExampleField(forms.fields.MultiValueField):
52     def __init__(self, count, *args, **kwargs):
53         self.count=count
54         self.widget = MultiWidgetBasic(self.count)
55         list_fields = []
56         for i in range(self.count):
57            list_fields.append(forms.fields.CharField(max_length=15))
58         super(MultiExampleField, self).__init__(list_fields, *args, **kwargs)
59
60     def compress(self, values):
61         ## compress list to single object                                               
62         return json.dumps(values)
63
64
65 class TaskForm(forms.Form):
66     name = forms.CharField(max_length=20)
67
68
69 class TaskForm_min(forms.Form):
70      name = forms.CharField(max_length=20)
71      file1 = forms.FileField(label='Upload a PDB file',required=False,
72       help_text='continuous (without breaks) protein chains,use TER to divide chains')
73      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
74       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
75       label='or PDB code')                   
76
77      def clean(self):
78              cleaned_data = super(TaskForm_min, self).clean()
79
80              pdbid = cleaned_data.get("pdbid") 
81              file1 = cleaned_data.get("file1")
82               
83              if not pdbid and not file1:
84                 msg = 'provide pdb file or pdb code'
85                 self.add_error('file1', msg)
86               
87              if pdbid:
88                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
89                if test.code != 200:
90                  msg = 'wrong pdb code'
91                  self.add_error('pdbid', msg)
92                else:
93                  msg=pdb_missing_res(test)
94                  if msg != '':
95                    self.add_error('pdbid',msg)
96                test.close()
97                
98              if file1:
99                  msg=pdb_missing_res(file1)
100                  if msg != '':
101                    self.add_error('file1',msg)
102
103             
104 class TaskForm_min_a(forms.Form):
105      name = forms.CharField(max_length=20)
106
107      unres_ff = forms.ChoiceField(choices=FF_CHOICE,widget=forms.RadioSelect,
108                            label='Force Field',initial='E0LL2Y')
109      min_choice = forms.ChoiceField(choices=MIN_CHOICE,label='minimization algorithm')
110      min_overlap = forms.BooleanField(required=False,label='remove overlap')
111      min_searchsc = forms.BooleanField(required=False,label='MC for sidechain overlap')
112      min_maxmin = forms.IntegerField(label='MAXMIN',initial=10000,
113                   help_text='maximum number of iterations')
114      min_maxfun = forms.IntegerField(label='MAXFUN',initial=15000,
115                   help_text='maximum number of function evaluations')
116      file1 = forms.FileField(label='Upload a PDB file',required=False,
117         help_text='continuous (without breaks) protein chains,use TER to divide chains')
118      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
119       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
120       label='or PDB code')                   
121
122      min_unres_pdb = forms.BooleanField(required=False,label='uploaded input unres PDB',
123                   help_text='(CA and CB atoms only, CB represents SC in UNRES)')
124      min_pdbout = forms.BooleanField(required=False,label='output PDB',initial='true')
125      boxx = forms.FloatField(label='Box X',initial=1000.0,
126                        help_text='box x dimension')
127      boxy = forms.FloatField(label='Box Y',initial=1000.0,
128                        help_text='box y dimension')
129      boxz = forms.FloatField(label='Box Z',initial=1000.0,
130                        help_text='box z dimension')
131
132      def clean(self):
133              cleaned_data = super(TaskForm_min_a, self).clean()
134
135              pdbid = cleaned_data.get("pdbid") 
136              file1 = cleaned_data.get("file1")
137               
138              if not pdbid and not file1:
139                 msg = 'provide pdb file or pdb code'
140                 self.add_error('file1', msg)
141               
142              if pdbid:
143                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
144                if test.code != 200:
145                  msg = 'wrong pdb code'
146                  self.add_error('pdbid', msg)
147                else:
148                  msg=pdb_missing_res(test)
149                  if msg != '':
150                    self.add_error('pdbid',msg)
151                test.close()
152                
153              if file1:
154                  msg=pdb_missing_res(file1)
155                  if msg != '':
156                    self.add_error('file1',msg)
157
158
159 class TaskForm_md(forms.Form):
160      name = forms.CharField(max_length=20)
161
162      md_start = forms.ChoiceField(choices=MD_START,widget=forms.RadioSelect,
163                       label='starting structure',initial='extconf')
164      md_seq = forms.CharField(label='Sequence',
165                      help_text='aminoacid sequence using one letter code<br>'+
166                      'field is ignored when uploading starting/reference PDB file',
167                      required=False,
168                      widget=forms.Textarea(attrs={'cols': 70, 'rows': 2}))
169      file1 = forms.FileField(label='Upload a PDB file',required=False,
170                   help_text='starting structure for pdbstart/reference structure')
171      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
172       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
173       label='or PDB code')                   
174      md_pdbref = forms.BooleanField(required=False,label='PDB reference structure')
175      md_temp = forms.FloatField(label='temperature',initial=300,
176                   help_text='bath temperature')
177      md_nstep = forms.IntegerField(label='NSTEP',initial=200000,
178                   help_text='total number of steps')
179      md_seed = forms.IntegerField(label='SEED',initial=-39912345,
180                   help_text='seed for random number generator')
181                   
182      def clean(self):
183              cleaned_data = super(TaskForm_md, self).clean()
184
185              md_start = cleaned_data.get("md_start") 
186              file1 = cleaned_data.get("file1")
187              pdbid = cleaned_data.get("pdbid")
188              md_seq = cleaned_data.get("md_seq")
189              md_pdbref = cleaned_data.get("md_pdbref")
190               
191              if md_start == 'pdbstart' and not (file1 or pdbid):
192                 msg = 'pdbstart with no PDB file or code'
193                 self.add_error('file1', msg)
194
195              if md_pdbref and not (file1 or pdbid):
196                 msg = 'pdbref with no PDB file or code'
197                 self.add_error('file1', msg)
198
199
200              if md_start != 'pdbstart' and not md_pdbref and not md_seq:
201                 msg = 'extended/random chain with no sequence'
202                 self.add_error('md_seq', msg)
203
204              if pdbid:
205                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
206                if test.code != 200:
207                  msg = 'wrong pdb code'
208                  self.add_error('pdbid', msg)
209                else:
210                  msg=pdb_missing_res(test)
211                  if msg != '':
212                    self.add_error('pdbid',msg)
213                test.close()
214                
215              if file1:
216                  msg=pdb_missing_res(file1)
217                  if msg != '':
218                    self.add_error('file1',msg)
219
220                         
221 class TaskForm_md_a(forms.Form):
222      name = forms.CharField(max_length=20)
223
224      unres_ff = forms.ChoiceField(choices=FF_CHOICE,widget=forms.RadioSelect,
225                            label='Force Field',initial='E0LL2Y')
226      md_start = forms.ChoiceField(choices=MD_START,widget=forms.RadioSelect,
227                       label='starting structure',initial='extconf')
228      md_seq = forms.CharField(label='Sequence',
229                      help_text='aminoacid sequence using one letter code<br>'+
230                      'field is ignored when uploading starting/reference PDB file',
231                      required=False,
232                      widget=forms.Textarea(attrs={'cols': 70, 'rows': 2}))
233      file1 = forms.FileField(label='Upload a PDB file',required=False,
234                   help_text='starting structure for pdbstart/reference structure')
235      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
236       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
237       label='or PDB code')                   
238      md_pdbref = forms.BooleanField(required=False,label='PDB reference structure')                  
239      md_temp = forms.FloatField(label='temperature',initial=300,
240                   help_text='bath temperature')
241      md_nstep = forms.IntegerField(label='NSTEP',initial=200000,
242                   help_text='total number of steps')
243      md_seed = forms.IntegerField(label='SEED',initial=-39912345,
244                   help_text='seed for random number generator')
245
246      md_ntwe = forms.IntegerField(label='NTWE',initial=1000,
247                help_text='write statfile every ntwe steps')
248      md_ntwx = forms.IntegerField(label='NTWX',initial=1000,
249                help_text='write trajectory every ntwe steps')
250      md_dt = forms.FloatField(label='DT',initial=0.2,
251                   help_text='time step [mtu]')
252      md_lang = forms.ChoiceField(choices=MD_LANG,label='thermostat')
253      md_tau = forms.FloatField(label='tau_bath',initial=1.0,
254                   help_text='coupling to the thermal bath (Berendsen)')
255      md_scal_fric = forms.FloatField(label='scal_froc',initial=0.02,
256                   help_text='scaling of the friction coefficients (Langevin)')
257      md_respa = forms.BooleanField(required=False,initial=True,label='RESPA')
258      md_mdpdb = forms.BooleanField(required=False,label='trajectory as PDB')
259
260      boxx = forms.FloatField(label='Box X',initial=1000.0,
261                        help_text='box x dimension')
262      boxy = forms.FloatField(label='Box Y',initial=1000.0,
263                        help_text='box y dimension')
264      boxz = forms.FloatField(label='Box Z',initial=1000.0,
265                        help_text='box z dimension')
266
267      def clean(self):
268              cleaned_data = super(TaskForm_md_a, self).clean()
269
270              md_start = cleaned_data.get("md_start") 
271              file1 = cleaned_data.get("file1")
272              pdbid = cleaned_data.get("pdbid")
273              md_seq = cleaned_data.get("md_seq")
274              md_pdbref = cleaned_data.get("md_pdbref")
275               
276              if md_start == 'pdbstart' and not (file1 or pdbid):
277                 msg = 'pdbstart with no PDB file or code'
278                 self.add_error('file1', msg)
279
280              if md_pdbref and not (file1 or pdbid):
281                 msg = 'pdbref with no PDB file or code'
282                 self.add_error('file1', msg)
283
284
285              if md_start != 'pdbstart' and not md_pdbref and not md_seq:
286                 msg = 'extended/random chain with no sequence'
287                 self.add_error('md_seq', msg)
288
289              if pdbid:
290                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
291                if test.code != 200:
292                  msg = 'wrong pdb code'
293                  self.add_error('pdbid', msg)
294                else:
295                  msg=pdb_missing_res(test)
296                  if msg != '':
297                    self.add_error('pdbid',msg)
298                test.close()
299                
300              if file1:
301                  msg=pdb_missing_res(file1)
302                  if msg != '':
303                    self.add_error('file1',msg)
304
305
306 class TaskForm_remd(forms.Form):
307      name = forms.CharField(max_length=20)
308
309      md_start = forms.ChoiceField(choices=MD_START,widget=forms.RadioSelect,
310                       label='starting structure',initial='extconf')
311      md_seq = forms.CharField(label='Sequence',
312                      help_text='aminoacid sequence using one letter code<br>'+
313                         'field is ignored when uploading starting/reference PDB file',
314                      required=False,
315                      widget=forms.Textarea(attrs={'cols': 70, 'rows': 2}))
316      file1 = forms.FileField(label='Upload a PDB file',required=False,
317                   help_text='starting structure for pdbstart/reference structure')
318      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
319       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
320       label='or PDB code')                   
321      md_pdbref = forms.BooleanField(required=False,label='PDB reference structure')                  
322      md_nstep = forms.IntegerField(label='NSTEP',initial=200000,
323                   help_text='total number of steps')
324      md_seed = forms.IntegerField(label='SEED',initial=-39912345,
325                   help_text='seed for random number generator')
326                   
327      def clean(self):
328              cleaned_data = super(TaskForm_remd, self).clean()
329
330              md_start = cleaned_data.get("md_start") 
331              file1 = cleaned_data.get("file1")
332              pdbid = cleaned_data.get("pdbid")
333              md_seq = cleaned_data.get("md_seq")
334              md_pdbref = cleaned_data.get("md_pdbref")
335               
336              if md_start == 'pdbstart' and not (file1 or pdbid):
337                 msg = 'pdbstart with no PDB file or code'
338                 self.add_error('file1', msg)
339
340              if md_pdbref and not (file1 or pdbid):
341                 msg = 'pdbref with no PDB file or code'
342                 self.add_error('file1', msg)
343
344              if md_start != 'pdbstart' and not md_pdbref and not md_seq:
345                 msg = 'extended/random chain with no sequence'
346                 self.add_error('md_seq', msg)
347
348              if pdbid:
349                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
350                if test.code != 200:
351                  msg = 'wrong pdb code'
352                  self.add_error('pdbid', msg)
353                else:
354                  msg=pdb_missing_res(test)
355                  if msg != '':
356                    self.add_error('pdbid',msg)
357                test.close()
358                
359              if file1:
360                  msg=pdb_missing_res(file1)
361                  if msg != '':
362                    self.add_error('file1',msg)
363
364                              
365 class TaskForm_remd_a(forms.Form):
366      name = forms.CharField(max_length=20)
367
368      unres_ff = forms.ChoiceField(choices=FF_CHOICE,widget=forms.RadioSelect,
369                            label='Force Field',initial='E0LL2Y')
370      md_start = forms.ChoiceField(choices=MD_START,widget=forms.RadioSelect,
371                       label='starting structure',initial='extconf')
372      md_seq = forms.CharField(label='Sequence',
373                      help_text='aminoacid sequence using one letter code<br>'+
374                       'field is ignored when uploading starting/reference PDB file',
375                      required=False,
376                      widget=forms.Textarea(attrs={'cols': 70, 'rows': 2}))
377      file1 = forms.FileField(label='Upload a PDB file',required=False,
378                   help_text='starting structure for pdbstart/reference structure')
379      pdbid = forms.CharField(min_length=4,max_length=4,required=False,
380       widget=forms.TextInput(attrs={'size':4, 'maxlength':4, 'title':'PDB code'}),
381       label='or PDB code')                   
382      md_pdbref = forms.BooleanField(required=False,label='PDB reference structure')                  
383      md_nstep = forms.IntegerField(label='NSTEP',initial=200000,
384                   help_text='total number of steps')
385      md_seed = forms.IntegerField(label='SEED',initial=-39912345,
386                   help_text='seed for random number generator')
387      md_ntwe = forms.IntegerField(label='NTWE',initial=1000,
388                help_text='write statfile every ntwe steps')
389      md_dt = forms.FloatField(label='DT',initial=0.2,
390                   help_text='time step [mtu]')
391      md_lang = forms.ChoiceField(choices=MD_LANG,label='thermostat')
392      md_tau = forms.FloatField(label='tau_bath',initial=1.0,
393                   help_text='coupling to the thermal bath (Berendsen)')
394      md_scal_fric = forms.FloatField(label='scal_froc',initial=0.02,
395                   help_text='scaling of the friction coefficients (Langevin)')
396      remd_nrep = forms.IntegerField(label='NREP',initial=8,
397                   help_text='number of replicas')
398      remd_nstex = forms.IntegerField(label='NSTEX',initial=1000,
399                   help_text='exchange and write trajectory every nstex steps')
400      md_ntwx = forms.IntegerField(label='NTWX',initial=1000,
401                help_text='write trajectory every ntwx steps')
402      remd_cluter_temp = forms.FloatField(label='TEMPER',
403                   help_text='temperature for cluster analysis',initial=280)                  
404 #     remd_traj1file = forms.BooleanField(required=False,label='single trajectory file',initial='true')
405 #     remd_rest1file = forms.BooleanField(required=False,label='single restart file',initial='true')
406
407      md_respa = forms.BooleanField(required=False,initial=True,label='RESPA')
408
409      boxx = forms.FloatField(label='Box X',initial=1000.0,
410                        help_text='box x dimension')
411      boxy = forms.FloatField(label='Box Y',initial=1000.0,
412                        help_text='box y dimension')
413      boxz = forms.FloatField(label='Box Z',initial=1000.0,
414                        help_text='box z dimension')
415
416
417      wsaxs = forms.FloatField(label='SAXS weight',initial=100.0,
418                             help_text='weight for SAXS restraint term')
419      scal_rad = forms.FloatField(label='Scal_rad (SAXS)',initial=1.0,
420                             help_text='downscaling factor of residue radii used in SAXS restraints')
421      saxs_data = forms.CharField(label='P(r) SAXS data',
422                      help_text='distance distribution from SAXS, two columns: r and P(r)',
423                      required=False,
424                      widget=forms.Textarea(attrs={'cols': 25, 'rows': 20}))
425
426
427      def clean(self):
428              cleaned_data = super(TaskForm_remd_a, self).clean()
429
430              md_start = cleaned_data.get("md_start") 
431              file1 = cleaned_data.get("file1")
432              pdbid = cleaned_data.get("pdbid")
433              md_seq = cleaned_data.get("md_seq")
434              md_pdbref = cleaned_data.get("md_pdbref")
435               
436              if md_start == 'pdbstart' and not (file1 or pdbid):
437                 msg = 'pdbstart with no PDB file or code'
438                 self.add_error('file1', msg)
439
440              if md_pdbref and not (file1 or pdbid):
441                 msg = 'pdbref with no PDB file or code'
442                 self.add_error('file1', msg)
443
444
445              if md_start != 'pdbstart' and not md_pdbref and not md_seq:
446                 msg = 'extended/random chain with no sequence'
447                 self.add_error('md_seq', msg)
448
449              if pdbid:
450                test=urllib.urlopen('http://files.rcsb.org/download/'+pdbid+'.pdb')     
451                if test.code != 200:
452                  msg = 'wrong pdb code'
453                  self.add_error('pdbid', msg)
454                else:
455                  msg=pdb_missing_res(test)
456                  if msg != '':
457                    self.add_error('pdbid',msg)
458                test.close()
459                
460              if file1:
461                  msg=pdb_missing_res(file1)
462                  if msg != '':
463                    self.add_error('file1',msg)
464
465
466
467 class TaskForm_list(forms.Form):
468     name = forms.CharField(max_length=20,disabled=True,required=False)
469     nrep = forms.IntegerField(disabled=True,required=False,label='NREP')
470
471     def __init__(self, count, *args, **kwargs):
472         super(TaskForm_list, self).__init__(*args, **kwargs)
473         self.count=count
474         self.fields['temperatures'] = MultiExampleField(self.count)
475         self.fields['multiplexing'] = MultiExampleField(self.count)        
476      
477
478