clean-up
[qcg-portal.git] / qcg / utils.py
1 # coding=utf-8
2 import os
3 import string
4 import random
5
6 from django.core.paginator import Paginator
7 from django.utils.formats import date_format
8 from django.utils.timezone import localtime
9 from pyqcg import QCG
10 from pyqcg.utils import Credential
11 from pyqcg.description import JobDescription
12
13 from filex.ftp import FTPOperation
14 from qcg import constants
15
16 from django.utils import encoding
17
18 def get_attributes(obj, attrs):
19     return {name: getattr(obj, name) for name in attrs if getattr(obj, name) is not None}
20
21
22 def username_from_dn(dn):
23     _, username = dn.rsplit('=', 1)
24
25     return username
26
27
28 def try_parse_int(s, default=None, base=10):
29     try:
30         return int(s, base)
31     except (TypeError, ValueError):
32         return default
33
34
35 def paginator_context(request, objects, per_page=constants.PER_PAGE):
36     paginator = Paginator(objects, per_page)
37
38     page_num = try_parse_int(request.GET.get('page'), 1)
39     if not (1 <= page_num <= paginator.num_pages):
40         page_num = 1
41
42     pages_range = range(max(2, min(page_num - 2, paginator.num_pages - 4)),
43                         min(max(page_num + 2, 5), paginator.num_pages) + 1)
44
45     return {'page': paginator.page(page_num), 'num_pages': paginator.num_pages, 'pages_range': pages_range}
46
47
48 def localtime_str(datetime):
49     return date_format(localtime(datetime), 'DATETIME_FORMAT')
50
51
52 def random_id(size=8, chars=string.ascii_uppercase + string.digits):
53     return ''.join(random.choice(chars) for _ in range(size))
54
55
56 def chunks(seq, size):
57     return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
58
59 def generate_md_inputfile(params):
60     md_input = list()
61     # Opis pliku wyjsciowego
62     opis=params['note'][:80]
63     md_input.append(encoding.smart_str(opis, encoding='ascii', errors='ignore'))
64     # Dane kontrolne obliczen
65     md_input.append('SEED=-3059743 PDBREF ONE_LETTER MD EXTCONF RESCALE_MODE=2')
66     ctl_data='nstep='+str(params['nstep'])+' ntwe='+str(params['ntwe'])
67     ctl_data+=' ntwx='+str(params['ntwx'])+' dt='+str(params['dt'])+' damax='+str(params['damax'])+'lang=0 tbf'
68     md_input.append('{:<79}&'.format(ctl_data))
69     md_input.append('tau_bath=1.0 t_bath=300 reset_vel=10000 respa ntime_split=1 maxtime_split=512')
70     # Paramatry pól siłowych
71     if params['force_field'] == 'GAB':
72         # Wagi pola GAB
73         md_input.append('WLONG=1.35279 WSCP=1.59304 WELEC=0.71534 WBOND=1.00000 WANG=1.13873            &')
74         md_input.append('WSCLOC=0.16258 WTOR=1.98599 WTORD=1.57069 WCORRH=0.42887 WCORR5=0.00000        &')
75         md_input.append('WCORR6=0.00000 WEL_LOC=0.16036 WTURN3=1.68722 WTURN4=0.66230 WTURN6=0.00000    &')
76         md_input.append('WVDWPP=0.11371 WHPB=1.00000                                                    &')
77         md_input.append('CUTOFF=7.00000 WCORR4=0.00000 WSCCOR=0.0')
78     else:
79         # Wagi pola E0LLY
80         md_input.append('WLONG=1.00000 WSCP=1.23315 WELEC=0.84476 WBOND=1.00000 WANG=0.62954            &')
81         md_input.append('WSCLOC=0.10554 WTOR=1.84316 WTORD=1.26571 WCORRH=0.19212 WCORR5=0.00000        &')
82         md_input.append('WCORR6=0.00000 WEL_LOC=0.37357 WTURN3=1.40323 WTURN4=0.64673 WTURN6=0.00000    &')
83         md_input.append('WVDWPP=0.23173 WHPB=1.00000 WSCCOR=0.0                                         &')
84         md_input.append('CUTOFF=7.00000 WCORR4=0.00000')
85     # Plik PDB    
86     md_input.append(params['pdb_file'].split('/')[-1])
87     # Sekwencja aminokwasów
88     md_input.append(len(params['sequence']))
89     seq_str=params['sequence']
90     while seq_str:
91         md_input.append(seq_str[:80])
92         seq_str=seq_str[80:]
93     md_input.append(' 0')
94     md_input.append(' 0')
95     
96     return md_input
97
98
99 def to_job_desc(params, proxy):
100     QCG.start()
101     desc = JobDescription(Credential(proxy))
102
103     direct_map = ('env_variables', 'executable', 'arguments', 'note', 'grant', 'hosts', 'properties', 'queue', 'procs',
104                   'wall_time', 'memory', 'memory_per_slot', 'modules', 'input', 'stage_in', 'native', 'notify',
105                   'preprocess', 'postprocess', 'persistent')
106
107     for name in direct_map:
108         if params[name]:
109             setattr(desc, name, params[name])
110
111     if params['application']:
112         desc.set_application(*params['application'])
113         desc.stage_in += [params['master_file']]
114         desc.arguments.insert(0, os.path.basename(params['master_file']))
115     if params['script']:
116         ftp = FTPOperation(proxy)
117
118         ftp.mkdir(constants.QCG_DATA_URL, parents=True)
119         url = os.path.join(constants.QCG_DATA_URL, 'script.{}.sh'.format(random_id()))
120         ftp.put(url)
121
122         for chunk in chunks(params['script'], 4096):
123             ftp.stream.put(chunk)
124         ftp.stream.put(None)
125         ftp.wait()
126
127         desc.executable = url
128     if params['nodes']:
129         desc.set_nodes(*params['nodes'])
130     if params['reservation']:
131         desc.set_reservation(params['reservation'])
132     if params['watch_output']:
133         desc.set_watch_output(params['watch_output'], params['watch_output_pattern'])
134
135     # TODO monitoring
136
137     print desc.sequence
138     
139     return desc
140
141
142 def to_form_data(xml):
143     # prevent circular import errors
144     from forms import JobDescriptionForm
145
146     QCG.start()
147     desc = JobDescription()
148     desc.xml_description = xml
149
150     direct_map = ('env_variables', 'executable', 'arguments', 'note', 'grant', 'hosts', 'properties', 'queue', 'procs',
151                   'wall_time', 'memory', 'memory_per_slot', 'modules', 'input', 'stage_in', 'native', 'persistent')
152
153     params = {}
154     for name in direct_map:
155         attr = getattr(desc, name)
156         if isinstance(attr, bool) or attr:
157             params[name] = attr
158
159     if desc.application is not None:
160         app_name, app_ver = desc.application
161         params['application'] = app_name if app_ver is None else app_name + '/' + app_name
162         stage_in = params['stage_in']
163         params['stage_in'], params['master_file'] = stage_in[:-1], stage_in[-1]
164         params['arguments'] = params['arguments'][1:]
165     if desc.nodes is not None:
166         params['nodes'] = ':'.join(map(str, desc.nodes))
167     if desc.reservation is not None:
168         res_id, res_type = desc.reservation
169         params['reservation'] = res_id
170     if desc.notify is not None:
171         params['notify_type'], params['notify_address'] = desc.notify.split(':')
172     if desc.watch_output is not None:
173         watch_output, params['watch_output_pattern'] = desc.watch_output
174         params['watch_output_type'], params['watch_output_address'] = watch_output.split(':')
175     if desc.preprocess is not None:
176         if desc.preprocess.startswith('gsiftp://'):
177             params['preprocess_type'] = JobDescriptionForm.Process.SCRIPT
178             params['preprocess_script'] = desc.preprocess
179         else:
180             params['preprocess_type'] = JobDescriptionForm.Process.CMD
181             params['preprocess_cmd'] = desc.preprocess
182     if desc.postprocess is not None:
183         if desc.postprocess.startswith('gsiftp://'):
184             params['postprocess_type'] = JobDescriptionForm.Process.SCRIPT
185             params['postprocess_script'] = desc.postprocess
186         else:
187             params['postprocess_type'] = JobDescriptionForm.Process.CMD
188             params['postprocess_cmd'] = desc.postprocess
189
190     return params