1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from math import pi
24 from os import F_OK, P_WAIT, access, chdir, chmod, getcwd, listdir, remove, system
25 from re import match, search
26 from string import count, find, split
27
28
29 try:
30 from os import spawnlp
31 except ImportError:
32 pass
33
34
37 """Class used to create and process input and output for the program Modelfree 4."""
38
39 self.relax = relax
40
41
42 - def create(self, run, dir, force, binary, diff_search, sims, sim_type, trim, steps, constraints, nucleus, atom1, atom2):
43 """Function for creating the Modelfree4 input files.
44
45 The following files are created:
46 dir/mfin
47 dir/mfdata
48 dir/mfpar
49 dir/mfmodel
50 dir/run.sh
51 """
52
53
54 if not run in self.relax.data.run_names:
55 raise RelaxNoRunError, run
56
57
58 if not self.relax.data.res.has_key(run):
59 raise RelaxNoSequenceError, run
60
61
62 if not self.relax.data.diff[run].type == 'sphere' and not self.relax.data.pdb.has_key(run):
63 raise RelaxNoPdbError, run
64
65
66 if not hasattr(self.relax.data, 'gx'):
67 raise RelaxNucleusError
68
69
70 if dir == None:
71 dir = run
72 self.relax.IO.mkdir(dir, print_flag=0)
73
74
75 self.run = run
76 self.dir = dir
77 self.force = force
78 self.binary = binary
79 self.diff_search = diff_search
80 self.sims = sims
81 self.sim_type = sim_type
82 self.trim = trim
83 self.steps = steps
84 self.constraints = constraints
85 self.nucleus = nucleus
86 self.atom1 = atom1
87 self.atom2 = atom2
88
89
90 self.num_frq = 0
91 self.frq = []
92 for i in xrange(len(self.relax.data.res[self.run])):
93 if hasattr(self.relax.data.res[self.run][i], 'num_frq'):
94 if self.relax.data.res[self.run][i].num_frq > self.num_frq:
95
96 self.num_frq = self.relax.data.res[self.run][i].num_frq
97
98
99 for frq in self.relax.data.res[self.run][i].frq:
100 if frq not in self.frq:
101 self.frq.append(frq)
102
103
104 mfin = self.open_file('mfin')
105 self.create_mfin(mfin)
106 mfin.close()
107
108
109 mfdata = self.open_file('mfdata')
110 mfmodel = self.open_file('mfmodel')
111 mfpar = self.open_file('mfpar')
112
113
114 for i in xrange(len(self.relax.data.res[self.run])):
115 if hasattr(self.relax.data.res[self.run][i], 'num_frq'):
116
117 if not self.create_mfdata(i, mfdata):
118 continue
119
120
121 self.create_mfmodel(i, mfmodel)
122
123
124 self.create_mfpar(i, mfpar)
125
126
127 mfdata.close()
128 mfmodel.close()
129 mfpar.close()
130
131
132 run = self.open_file('run.sh')
133 self.create_run(run)
134 run.close()
135 chmod(self.dir + '/run.sh', 0755)
136
137
139 """Create the Modelfree4 input file 'mfmodel'."""
140
141
142 file.write("\nspin " + self.relax.data.res[self.run][i].name + "_" + `self.relax.data.res[self.run][i].num` + "\n")
143
144
145 written = 0
146
147
148 for j in xrange(self.num_frq):
149
150 r1, r2, noe = None, None, None
151
152
153 for k in xrange(self.relax.data.res[self.run][i].num_ri):
154 if self.frq[j] != self.relax.data.res[self.run][i].frq[self.relax.data.res[self.run][i].remap_table[k]]:
155 continue
156
157
158 if self.relax.data.res[self.run][i].ri_labels[k] == 'R1':
159 r1 = self.relax.data.res[self.run][i].relax_data[k]
160 r1_err = self.relax.data.res[self.run][i].relax_error[k]
161
162
163 elif self.relax.data.res[self.run][i].ri_labels[k] == 'R2':
164 r2 = self.relax.data.res[self.run][i].relax_data[k]
165 r2_err = self.relax.data.res[self.run][i].relax_error[k]
166
167
168 elif self.relax.data.res[self.run][i].ri_labels[k] == 'NOE':
169 noe = self.relax.data.res[self.run][i].relax_data[k]
170 noe_err = self.relax.data.res[self.run][i].relax_error[k]
171
172
173 if r1:
174 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R1', self.frq[j]*1e-6, r1, r1_err, 1))
175 else:
176 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R1', self.frq[j]*1e-6, 0, 0, 0))
177
178
179 if r2:
180 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R2', self.frq[j]*1e-6, r2, r2_err, 1))
181 else:
182 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R2', self.frq[j]*1e-6, 0, 0, 0))
183
184
185 if noe:
186 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('NOE', self.frq[j]*1e-6, noe, noe_err, 1))
187 else:
188 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('NOE', self.frq[j]*1e-6, 0, 0, 0))
189
190 written = 1
191
192 return written
193
194
196 """Create the Modelfree4 input file 'mfin'."""
197
198
199 if self.relax.data.diff[self.run].type == 'sphere':
200 diff = 'isotropic'
201 algorithm = 'brent'
202 tm = self.relax.data.diff[self.run].tm / 1e-9
203 dratio = 1
204 theta = 0
205 phi = 0
206 elif self.relax.data.diff[self.run].type == 'spheroid':
207 diff = 'axial'
208 algorithm = 'powell'
209 tm = self.relax.data.diff[self.run].tm / 1e-9
210 dratio = self.relax.data.diff[self.run].Dratio
211 theta = self.relax.data.diff[self.run].theta * 360.0 / (2.0 * pi)
212 phi = self.relax.data.diff[self.run].phi * 360.0 / (2.0 * pi)
213 elif self.relax.data.diff[self.run].type == 'ellipsoid':
214 diff = 'anisotropic'
215 algorithm = 'powell'
216 tm = self.relax.data.diff[self.run].tm / 1e-9
217 dratio = 0
218 theta = 0
219 phi = 0
220
221
222 file.write("optimization tval\n\n")
223 file.write("seed 0\n\n")
224 file.write("search grid\n\n")
225
226
227 if self.relax.data.diff[self.run].fixed:
228 algorithm = 'fix'
229
230 file.write("diffusion " + diff + " " + self.diff_search + "\n\n")
231 file.write("algorithm " + algorithm + "\n\n")
232
233
234 if self.sims:
235 file.write("simulations " + self.sim_type + " " + `self.sims` + " " + `self.trim` + "\n\n")
236 else:
237 file.write("simulations none\n\n")
238
239 selection = 'none'
240 file.write("selection " + selection + "\n\n")
241 file.write("sim_algorithm " + algorithm + "\n\n")
242
243 file.write("fields " + `self.num_frq`)
244 for frq in self.frq:
245 file.write(" " + `frq*1e-6`)
246 file.write("\n")
247
248
249 file.write('%-7s' % 'tm')
250 file.write('%14.3f' % tm)
251 file.write('%2i' % 1)
252 file.write('%3i' % 0)
253 file.write('%5i' % 5)
254 file.write('%6i' % 15)
255 file.write('%4i\n' % 20)
256
257
258 file.write('%-7s' % 'Dratio')
259 file.write('%14s' % dratio)
260 file.write('%2i' % 1)
261 file.write('%3i' % 0)
262 file.write('%5i' % 0)
263 file.write('%6i' % 2)
264 file.write('%4i\n' % 5)
265
266
267 file.write('%-7s' % 'Theta')
268 file.write('%14s' % theta)
269 file.write('%2i' % 1)
270 file.write('%3i' % 0)
271 file.write('%5i' % 0)
272 file.write('%6i' % 180)
273 file.write('%4i\n' % 10)
274
275
276 file.write('%-7s' % 'Phi')
277 file.write('%14s' % phi)
278 file.write('%2i' % 1)
279 file.write('%3i' % 0)
280 file.write('%5i' % 0)
281 file.write('%6i' % 360)
282 file.write('%4i\n' % 10)
283
284
286 """Create the Modelfree4 input file 'mfmodel'."""
287
288
289 file.write("\nspin " + self.relax.data.res[self.run][i].name + "_" + `self.relax.data.res[self.run][i].num` + "\n")
290
291
292 file.write('%-3s%-6s%-6.1f' % ('M1', 'tloc', 0))
293 if 'tm' in self.relax.data.res[self.run][i].params:
294 file.write('%-4i' % 1)
295 else:
296 file.write('%-4i' % 0)
297
298 if self.constraints:
299 file.write('%-2i' % 2)
300 else:
301 file.write('%-2i' % 0)
302
303 file.write('%11.3f%12.3f %-4s\n' % (0, 20, self.steps))
304
305
306 file.write('%-3s%-6s%-6.1f' % ('M1', 'Theta', 0))
307 file.write('%-4i' % 0)
308
309 if self.constraints:
310 file.write('%-2i' % 2)
311 else:
312 file.write('%-2i' % 0)
313
314 file.write('%11.3f%12.3f %-4s\n' % (0, 90, self.steps))
315
316
317 file.write('%-3s%-6s%-6.1f' % ('M1', 'Sf2', 1))
318 if 'S2f' in self.relax.data.res[self.run][i].params:
319 file.write('%-4i' % 1)
320 else:
321 file.write('%-4i' % 0)
322
323 if self.constraints:
324 file.write('%-2i' % 2)
325 else:
326 file.write('%-2i' % 0)
327
328 file.write('%11.3f%12.3f %-4s\n' % (0, 1, self.steps))
329
330
331 file.write('%-3s%-6s%-6.1f' % ('M1', 'Ss2', 1))
332 if 'S2s' in self.relax.data.res[self.run][i].params or 'S2' in self.relax.data.res[self.run][i].params:
333 file.write('%-4i' % 1)
334 else:
335 file.write('%-4i' % 0)
336
337 if self.constraints:
338 file.write('%-2i' % 2)
339 else:
340 file.write('%-2i' % 0)
341
342 file.write('%11.3f%12.3f %-4s\n' % (0, 1, self.steps))
343
344
345 file.write('%-3s%-6s%-6.1f' % ('M1', 'te', 0))
346 if 'te' in self.relax.data.res[self.run][i].params or 'ts' in self.relax.data.res[self.run][i].params:
347 file.write('%-4i' % 1)
348 else:
349 file.write('%-4i' % 0)
350
351 if self.constraints:
352 file.write('%-2i' % 2)
353 else:
354 file.write('%-2i' % 0)
355
356 file.write('%11.3f%12.3f %-4s\n' % (0, 10000, self.steps))
357
358
359 file.write('%-3s%-6s%-6.1f' % ('M1', 'Rex', 0))
360 if 'Rex' in self.relax.data.res[self.run][i].params:
361 file.write('%-4i' % 1)
362 else:
363 file.write('%-4i' % 0)
364
365 if self.constraints:
366 file.write('%-2i' % -1)
367 else:
368 file.write('%-2i' % 0)
369
370 file.write('%11.3f%12.3f %-4s\n' % (0, 20, self.steps))
371
372
374 """Create the Modelfree4 input file 'mfpar'."""
375
376
377 file.write("\nspin " + self.relax.data.res[self.run][i].name + "_" + `self.relax.data.res[self.run][i].num` + "\n")
378
379 file.write('%-14s' % "constants")
380 file.write('%-6i' % self.relax.data.res[self.run][i].num)
381 file.write('%-7s' % self.nucleus)
382 file.write('%-8.3f' % (self.relax.data.gx / 1e7))
383 file.write('%-8.3f' % (self.relax.data.res[self.run][i].r * 1e10))
384 file.write('%-8.3f\n' % (self.relax.data.res[self.run][i].csa * 1e6))
385
386 file.write('%-10s' % "vector")
387 file.write('%-4s' % self.atom1)
388 file.write('%-4s\n' % self.atom2)
389
390
392 """Create the script 'run.sh' for the execution of Modelfree4."""
393
394 file.write("#! /bin/sh\n")
395 file.write(self.binary + " -i mfin -d mfdata -p mfpar -m mfmodel -o mfout -e out")
396 if self.relax.data.diff[self.run].type != 'sphere':
397
398 system('cp ' + self.relax.data.pdb[self.run].file_name + ' ' + self.dir)
399 file.write(" -s " + self.relax.data.pdb[self.run].file_name.split('/')[-1])
400 file.write("\n")
401
402
403 - def execute(self, run, dir, force, binary):
404 """Function for executing Modelfree4.
405
406 BUG: Control-C during execution causes the cwd to stay as dir.
407 """
408
409
410 self.run = run
411 self.dir = dir
412 self.force = force
413 self.binary = binary
414
415
416 orig_dir = getcwd()
417
418
419 if dir == None:
420 dir = run
421 if not access(dir, F_OK):
422 raise RelaxDirError, ('Modelfree4', dir)
423
424
425 chdir(dir)
426
427
428 try:
429
430 if not access('mfin', F_OK):
431 raise RelaxFileError, ('mfin input', 'mfin')
432
433
434 if not access('mfdata', F_OK):
435 raise RelaxFileError, ('mfdata input', 'mfdata')
436
437
438 if not access('mfmodel', F_OK):
439 raise RelaxFileError, ('mfmodel input', 'mfmodel')
440
441
442 if not access('mfpar', F_OK):
443 raise RelaxFileError, ('mfpar input', 'mfpar')
444
445
446 if self.relax.data.diff[run].type != 'sphere':
447 pdb = self.relax.data.pdb[self.run].file_name.split('/')[-1]
448 if not access(pdb, F_OK):
449 raise RelaxFileError, ('PDB', pdb)
450 else:
451 pdb = None
452
453
454 if force:
455 for file in listdir(getcwd()):
456 if search('out$', file) or search('rotate$', file):
457 remove(file)
458
459
460 self.relax.IO.test_binary(self.binary)
461
462
463 if pdb:
464 status = spawnlp(P_WAIT, self.binary, self.binary, '-i', 'mfin', '-d', 'mfdata', '-p', 'mfpar', '-m', 'mfmodel', '-o', 'mfout', '-e', 'out', '-s', pdb)
465 if status:
466 raise RelaxProgFailError, 'Modelfree4'
467
468
469
470 else:
471 status = spawnlp(P_WAIT, self.binary, self.binary, '-i', 'mfin', '-d', 'mfdata', '-p', 'mfpar', '-m', 'mfmodel', '-o', 'mfout', '-e', 'out')
472 if status:
473 raise RelaxProgFailError, 'Modelfree4'
474
475
476 except:
477
478 chdir(orig_dir)
479
480
481 raise
482
483
484 chdir(orig_dir)
485
486
488 """Function for extracting the Modelfree4 results out of the 'mfout' file."""
489
490
491 self.run = run
492
493
494 if not self.relax.data.res.has_key(self.run):
495 raise RelaxNoSequenceError, self.run
496
497
498 if dir == None:
499 dir = run
500 if not access(dir, F_OK):
501 raise RelaxDirError, ('Modelfree4', dir)
502
503
504 if not access(dir + "/mfout", F_OK):
505 raise RelaxFileError, ('Modelfree4', dir + "/mfout")
506
507
508 mfout_file = open(dir + "/mfout", 'r')
509 self.mfout_lines = mfout_file.readlines()
510 mfout_file.close()
511
512
513 self.line_positions()
514
515
516
517 sims = 0
518 for i in xrange(len(self.mfout_lines)):
519 if search('_iterations', self.mfout_lines[i]):
520 row = split(self.mfout_lines[i])
521 sims = int(row[1])
522
523
524 pos = 0
525 for i in xrange(len(self.relax.data.res[self.run])):
526
527 data = self.relax.data.res[self.run][i]
528
529
530 if not data.select:
531 continue
532
533
534 if not hasattr(data, 'model'):
535 continue
536
537
538 if not hasattr(data, 'num_frq'):
539 continue
540
541
542 if 'S2' in data.params:
543 data.s2, data.s2_err = self.get_mf_data(self.mfout_S2_pos + pos)
544
545
546 if 'S2f' in data.params or 'S2s' in data.params:
547 data.s2f, data.s2f_err = self.get_mf_data(self.mfout_S2f_pos + pos)
548
549
550 if 'S2f' in data.params or 'S2s' in data.params:
551 data.s2s, data.s2s_err = self.get_mf_data(self.mfout_S2s_pos + pos)
552
553
554 if 'te' in data.params:
555 data.te, data.te_err = self.get_mf_data(self.mfout_te_pos + pos)
556 data.te = data.te / 1e12
557 data.te_err = data.te_err / 1e12
558
559
560 if 'ts' in data.params:
561 data.ts, data.ts_err = self.get_mf_data(self.mfout_te_pos + pos)
562 data.ts = data.ts / 1e12
563 data.ts_err = data.ts_err / 1e12
564
565
566 if 'Rex' in data.params:
567 data.rex, data.rex_err = self.get_mf_data(self.mfout_Rex_pos + pos)
568 data.rex = data.rex / (2.0 * pi * data.frq[0])**2
569 data.rex_err = data.rex_err / (2.0 * pi * data.frq[0])**2
570
571
572 if not sims:
573 row = split(self.mfout_lines[self.mfout_chi2_pos + pos])
574 data.chi2 = float(row[1])
575 else:
576
577 row = split(self.mfout_lines[self.mfout_chi2_pos + 2 + 22*pos])
578 data.chi2 = float(row[1])
579
580
581 pos = pos + 1
582
583
585 """Extract the model-free data from the given position of the mfout file.
586
587 This method is designed to catch a number of bugs in Modelfree4's mfout file.
588
589 The first bug is the presence of a series of '*' characters causing a fusion of two columns.
590 This is handled by splitting by the '*' char and then returning the first element.
591
592 The second bug is when the floating point number is too big to fit into Modelfree4's string
593 format limit of 15.3f. This results in a results line such as:
594
595 246 10000.00019682363392.000 1 0.000 0.000 0.000 0.000
596
597 This is caught by scanning for two '.' characters in the column, and handled by assuming
598 that every floating point number will have three decimal characters.
599
600 @param pos: The mfout line position.
601 @type pos: int
602 @return: The value and error.
603 @rtype: tuple of 2 floats
604 """
605
606
607 row = split(self.mfout_lines[pos])
608
609
610 val = row[1]
611 err = row[4]
612
613
614 if search('\*', val) or search('\*', err):
615
616 val_row = split(val, '*')
617 err_row = split(err, '*')
618
619
620 val = val_row[0]
621 err = err_row[0]
622
623
624 new_row = []
625 fused = False
626 for element in row:
627
628 num = count(element, '.')
629
630
631 if num > 1:
632
633 fused = True
634
635
636 for i in xrange(num):
637
638 index = find(element, '.')
639
640
641 new_row.append(element[0:index+4])
642
643
644 element = element[index+4:]
645
646
647 else:
648 new_row.append(element)
649
650
651 if fused:
652 val = new_row[1]
653 err = new_row[4]
654
655
656 return float(val), float(err)
657
658
660 """Function for getting the section positions (line number) of the mfout file."""
661
662
663 i = 0
664 while i < len(self.mfout_lines):
665
666 if match('data_model_1', self.mfout_lines[i]):
667
668 i = i + 2
669
670
671 while 1:
672
673 if not self.mfout_lines[i] == '\n' and not search('^ ', self.mfout_lines[i]):
674 break
675
676
677 row = split(self.mfout_lines[i])
678
679
680 if len(row) == 2 and row[0] == 'S2':
681 self.mfout_S2_pos = i + 1
682
683
684 if len(row) == 2 and row[0] == 'S2f':
685 self.mfout_S2f_pos = i + 1
686
687
688 if len(row) == 2 and row[0] == 'S2s':
689 self.mfout_S2s_pos = i + 1
690
691
692 if len(row) == 2 and row[0] == 'te':
693 self.mfout_te_pos = i + 1
694
695
696 if len(row) == 2 and row[0] == 'Rex':
697 self.mfout_Rex_pos = i + 1
698
699
700 i = i + 1
701
702
703 if match('data_sse', self.mfout_lines[i]):
704 self.mfout_chi2_pos = i + 3
705
706
707 i = i + 1
708
709
711 """Function for opening a file to write to."""
712
713 file_name = self.dir + "/" + file_name
714 if access(file_name, F_OK) and not self.force:
715 raise RelaxFileOverwriteError, (file_name, 'force flag')
716 return open(file_name, 'w')
717