1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for interfacing with Art Palmer's Modelfree 4 program."""
24
25
26
27 import dep_check
28
29
30 from math import pi
31 from os import F_OK, access, chdir, chmod, getcwd, listdir, remove, sep, system
32 from re import match, search
33 from stat import S_IRWXU, S_IRGRP, S_IROTH
34 PIPE, Popen = None, None
35 if dep_check.subprocess_module:
36 from subprocess import PIPE, Popen
37 import sys
38
39
40 from lib.errors import RelaxError, RelaxDirError, RelaxFileError, RelaxNoInteratomError, RelaxNoModelError, RelaxNoPdbError, RelaxNoSequenceError, RelaxNoTensorError
41 from lib.io import mkdir_nofail, open_write_file, test_binary
42 from lib.periodic_table import periodic_table
43 from pipe_control import diffusion_tensor, pipes
44 from pipe_control.interatomic import return_interatom_list
45 from pipe_control.mol_res_spin import exists_mol_res_spin_data, spin_loop
46 from pipe_control.pipes import check_pipe
47 from specific_analyses.model_free.model import determine_model_type
48
49
75
76
77 -def create(dir=None, binary=None, diff_search=None, sims=None, sim_type=None, trim=None, steps=None, heteronuc_type=None, atom1=None, atom2=None, spin_id=None, force=False, constraints=True):
78 """Create the Modelfree4 input files.
79
80 The following files are created:
81 - dir/mfin
82 - dir/mfdata
83 - dir/mfpar
84 - dir/mfmodel
85 - dir/run.sh
86
87 @keyword dir: The optional directory to place the files into. If None, then the files will be placed into a directory named after the current data pipe.
88 @type dir: str or None
89 @keyword binary: The name of the Modelfree4 binary file. This can include the path to the binary.
90 @type binary: str
91 @keyword diff_search: The diffusion tensor search algorithm (see the Modelfree4 manual for details).
92 @type diff_search: str
93 @keyword sims: The number of Monte Carlo simulations to perform.
94 @type sims: int
95 @keyword sim_type: The type of simulation to perform (see the Modelfree4 manual for details).
96 @type sim_type: str
97 @keyword trim: Trimming of the Monte Carlo simulations (see the Modelfree4 manual for details).
98 @type trim: int
99 @keyword steps: The grid search size (see the Modelfree4 manual for details).
100 @type steps: int
101 @keyword heteronuc_type: The Modelfree4 three letter code for the heteronucleus type, e.g. '15N', '13C', etc.
102 @type heteronuc_type: str
103 @keyword atom1: The name of the heteronucleus in the PDB file.
104 @type atom1: str
105 @keyword atom2: The name of the proton in the PDB file.
106 @type atom2: str
107 @keyword spin_id: The spin identification string.
108 @type spin_id: str
109 @keyword force: A flag which if True will cause all pre-existing files to be overwritten.
110 @type force: bool
111 @keyword constraints: A flag which if True will result in constrained optimisation.
112 @type constraints: bool
113 """
114
115
116 check_pipe()
117
118
119 if not exists_mol_res_spin_data():
120 raise RelaxNoSequenceError
121
122
123 if hasattr(cdp, 'diff_tensor') and not cdp.diff_tensor.type == 'sphere' and not hasattr(cdp, 'structure'):
124 raise RelaxNoPdbError
125
126
127 __deselect_spins()
128
129
130 if dir == None:
131 dir = pipes.cdp_name()
132 mkdir_nofail(dir, verbosity=0)
133
134
135 frq = []
136 for ri_id in cdp.ri_ids:
137
138 if cdp.spectrometer_frq[ri_id] not in frq:
139 frq.append(cdp.spectrometer_frq[ri_id])
140
141
142 mfin = open_write_file('mfin', dir, force)
143 create_mfin(mfin, diff_search=diff_search, sims=sims, sim_type=sim_type, trim=trim, num_frq=len(frq), frq=frq)
144 mfin.close()
145
146
147 mfdata = open_write_file('mfdata', dir, force)
148 mfmodel = open_write_file('mfmodel', dir, force)
149 mfpar = open_write_file('mfpar', dir, force)
150
151
152 for spin, mol_name, res_num, res_name, id in spin_loop(spin_id, full_info=True, return_id=True):
153
154 if not spin.select:
155 continue
156
157
158 if not create_mfdata(mfdata, spin=spin, spin_id=id, num_frq=len(frq), frq=frq):
159 continue
160
161
162 create_mfmodel(mfmodel, spin=spin, spin_id=id, steps=steps, constraints=constraints)
163
164
165 create_mfpar(mfpar, spin=spin, spin_id=id, res_num=res_num, atom1=atom1, atom2=atom2)
166
167
168 mfdata.close()
169 mfmodel.close()
170 mfpar.close()
171
172
173 run = open_write_file('run.sh', dir, force)
174 create_run(run, binary=binary, dir=dir)
175 run.close()
176 chmod(dir + sep+'run.sh', S_IRWXU|S_IRGRP|S_IROTH)
177
178
179 -def create_mfdata(file, spin=None, spin_id=None, num_frq=None, frq=None):
180 """Create the Modelfree4 input file 'mfmodel'.
181
182 @param file: The writable file object.
183 @type file: file object
184 @param spin: The spin container.
185 @type spin: SpinContainer instance
186 @param spin_id: The spin identification string.
187 @type spin_id str
188 @keyword num_frq: The number of spectrometer frequencies relaxation data was collected at.
189 @type num_frq: int
190 @keyword frq: The spectrometer frequencies.
191 @type frq: list of float
192 @return: True if file data is written, False otherwise.
193 @rtype: bool
194 """
195
196
197 file.write("\nspin " + spin_id + "\n")
198
199
200 written = False
201
202
203 for j in range(num_frq):
204
205 r1, r2, noe = None, None, None
206
207
208 for ri_id in cdp.ri_ids:
209
210 if frq[j] != cdp.spectrometer_frq[ri_id]:
211 continue
212
213
214 if cdp.ri_type[ri_id] == 'R1':
215 r1 = spin.ri_data[ri_id]
216 r1_err = spin.ri_data_err[ri_id]
217
218
219 elif cdp.ri_type[ri_id] == 'R2':
220 r2 = spin.ri_data[ri_id]
221 r2_err = spin.ri_data_err[ri_id]
222
223
224 elif cdp.ri_type[ri_id] == 'NOE':
225 noe = spin.ri_data[ri_id]
226 noe_err = spin.ri_data_err[ri_id]
227
228
229 if r1:
230 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R1', frq[j]*1e-6, r1, r1_err, 1))
231 else:
232 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R1', frq[j]*1e-6, 0, 0, 0))
233
234
235 if r2:
236 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R2', frq[j]*1e-6, r2, r2_err, 1))
237 else:
238 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('R2', frq[j]*1e-6, 0, 0, 0))
239
240
241 if noe:
242 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('NOE', frq[j]*1e-6, noe, noe_err, 1))
243 else:
244 file.write('%-7s%-10.3f%20.15f%20.15f %-3i\n' % ('NOE', frq[j]*1e-6, 0, 0, 0))
245
246 written = True
247
248 return written
249
250
251 -def create_mfin(file, diff_search=None, sims=None, sim_type=None, trim=None, num_frq=None, frq=None):
252 """Create the Modelfree4 input file 'mfin'.
253
254 @param file: The writable file object.
255 @type file: file object
256 @keyword diff_search: The diffusion tensor search algorithm (see the Modelfree4 manual for
257 details).
258 @type diff_search: str
259 @keyword sims: The number of Monte Carlo simulations to perform.
260 @type sims: int
261 @keyword sim_type: The type of simulation to perform (see the Modelfree4 manual for
262 details).
263 @type sim_type: str
264 @keyword trim: Trimming of the Monte Carlo simulations (see the Modelfree4 manual for
265 details).
266 @type trim: int
267 @keyword num_frq: The number of spectrometer frequencies relaxation data was collected at.
268 @type num_frq: int
269 @keyword frq: The spectrometer frequencies.
270 @type frq: list of float
271 """
272
273
274 if not hasattr(cdp, 'diff_tensor'):
275 raise RelaxNoTensorError('diffusion')
276
277
278 if cdp.diff_tensor.type == 'sphere':
279 diff = 'isotropic'
280 algorithm = 'brent'
281 tm = cdp.diff_tensor.tm / 1e-9
282 dratio = 1
283 theta = 0
284 phi = 0
285 elif cdp.diff_tensor.type == 'spheroid':
286 diff = 'axial'
287 algorithm = 'powell'
288 tm = cdp.diff_tensor.tm / 1e-9
289 dratio = cdp.diff_tensor.Dratio
290 theta = cdp.diff_tensor.theta * 360.0 / (2.0 * pi)
291 phi = cdp.diff_tensor.phi * 360.0 / (2.0 * pi)
292 elif cdp.diff_tensor.type == 'ellipsoid':
293 diff = 'anisotropic'
294 algorithm = 'powell'
295 tm = cdp.diff_tensor.tm / 1e-9
296 dratio = 0
297 theta = 0
298 phi = 0
299
300
301 file.write("optimization tval\n\n")
302 file.write("seed 0\n\n")
303 file.write("search grid\n\n")
304
305
306 if cdp.diff_tensor.fixed:
307 algorithm = 'fix'
308
309 file.write("diffusion " + diff + " " + diff_search + "\n\n")
310 file.write("algorithm " + algorithm + "\n\n")
311
312
313 if sims:
314 file.write("simulations " + sim_type + " " + repr(sims) + " " + repr(trim) + "\n\n")
315 else:
316 file.write("simulations none\n\n")
317
318 selection = 'none'
319 file.write("selection " + selection + "\n\n")
320 file.write("sim_algorithm " + algorithm + "\n\n")
321
322 file.write("fields " + repr(num_frq))
323 for val in frq:
324 file.write(" " + repr(val*1e-6))
325 file.write("\n")
326
327
328 file.write('%-7s' % 'tm')
329 file.write('%14.3f' % tm)
330 file.write('%2i' % 1)
331 file.write('%3i' % 0)
332 file.write('%5i' % 5)
333 file.write('%6i' % 15)
334 file.write('%4i\n' % 20)
335
336
337 file.write('%-7s' % 'Dratio')
338 file.write('%14s' % dratio)
339 file.write('%2i' % 1)
340 file.write('%3i' % 0)
341 file.write('%5i' % 0)
342 file.write('%6i' % 2)
343 file.write('%4i\n' % 5)
344
345
346 file.write('%-7s' % 'Theta')
347 file.write('%14s' % theta)
348 file.write('%2i' % 1)
349 file.write('%3i' % 0)
350 file.write('%5i' % 0)
351 file.write('%6i' % 180)
352 file.write('%4i\n' % 10)
353
354
355 file.write('%-7s' % 'Phi')
356 file.write('%14s' % phi)
357 file.write('%2i' % 1)
358 file.write('%3i' % 0)
359 file.write('%5i' % 0)
360 file.write('%6i' % 360)
361 file.write('%4i\n' % 10)
362
363
364 -def create_mfmodel(file, spin=None, spin_id=None, steps=None, constraints=None):
365 """Create the Modelfree4 input file 'mfmodel'.
366
367 @param file: The writable file object.
368 @type file: file object
369 @keyword spin: The spin container.
370 @type spin: SpinContainer instance
371 @keyword spin_id: The spin identification string.
372 @type spin_id str
373 @keyword steps: The grid search size (see the Modelfree4 manual for details).
374 @type steps: int
375 @keyword constraints: A flag which if True will result in constrained optimisation.
376 @type constraints: bool
377 """
378
379
380 file.write("\nspin " + spin_id + "\n")
381
382
383 file.write('%-3s%-6s%-6.1f' % ('M1', 'tloc', 0))
384 if 'tm' in spin.params:
385 file.write('%-4i' % 1)
386 else:
387 file.write('%-4i' % 0)
388
389 if constraints:
390 file.write('%-2i' % 2)
391 else:
392 file.write('%-2i' % 0)
393
394 file.write('%11.3f%12.3f %-4s\n' % (0, 20, steps))
395
396
397 file.write('%-3s%-6s%-6.1f' % ('M1', 'Theta', 0))
398 file.write('%-4i' % 0)
399
400 if constraints:
401 file.write('%-2i' % 2)
402 else:
403 file.write('%-2i' % 0)
404
405 file.write('%11.3f%12.3f %-4s\n' % (0, 90, steps))
406
407
408 file.write('%-3s%-6s%-6.1f' % ('M1', 'Sf2', 1))
409 if 's2f' in spin.params:
410 file.write('%-4i' % 1)
411 else:
412 file.write('%-4i' % 0)
413
414 if constraints:
415 file.write('%-2i' % 2)
416 else:
417 file.write('%-2i' % 0)
418
419 file.write('%11.3f%12.3f %-4s\n' % (0, 1, steps))
420
421
422 file.write('%-3s%-6s%-6.1f' % ('M1', 'Ss2', 1))
423 if 's2s' in spin.params or 's2' in spin.params:
424 file.write('%-4i' % 1)
425 else:
426 file.write('%-4i' % 0)
427
428 if constraints:
429 file.write('%-2i' % 2)
430 else:
431 file.write('%-2i' % 0)
432
433 file.write('%11.3f%12.3f %-4s\n' % (0, 1, steps))
434
435
436 file.write('%-3s%-6s%-6.1f' % ('M1', 'te', 0))
437 if 'te' in spin.params or 'ts' in spin.params:
438 file.write('%-4i' % 1)
439 else:
440 file.write('%-4i' % 0)
441
442 if constraints:
443 file.write('%-2i' % 2)
444 else:
445 file.write('%-2i' % 0)
446
447 file.write('%11.3f%12.3f %-4s\n' % (0, 10000, steps))
448
449
450 file.write('%-3s%-6s%-6.1f' % ('M1', 'rex', 0))
451 if 'rex' in spin.params:
452 file.write('%-4i' % 1)
453 else:
454 file.write('%-4i' % 0)
455
456 if constraints:
457 file.write('%-2i' % -1)
458 else:
459 file.write('%-2i' % 0)
460
461 file.write('%11.3f%12.3f %-4s\n' % (0, 20, steps))
462
463
464 -def create_mfpar(file, spin=None, spin_id=None, res_num=None, atom1=None, atom2=None):
465 """Create the Modelfree4 input file 'mfpar'.
466
467 @param file: The writable file object.
468 @type file: file object
469 @keyword spin: The spin container.
470 @type spin: SpinContainer instance
471 @keyword spin_id: The spin identification string.
472 @type spin_id str
473 @keyword res_num: The residue number from the PDB file corresponding to the spin.
474 @type res_num: int
475 @keyword atom1: The name of the heteronucleus in the PDB file.
476 @type atom1: str
477 @keyword atom2: The name of the proton in the PDB file.
478 @type atom2: str
479 """
480
481
482 interatoms = return_interatom_list(spin_id)
483 if len(interatoms) == 0:
484 raise RelaxNoInteratomError
485 elif len(interatoms) > 1:
486 raise RelaxError("Only one interatomic data container, hence dipole-dipole interaction, is supported per spin.")
487
488
489 file.write("\nspin " + spin_id + "\n")
490
491 file.write('%-14s' % "constants")
492 file.write('%-6i' % res_num)
493 file.write('%-7s' % spin.isotope)
494 file.write('%-8.4f' % (periodic_table.gyromagnetic_ratio(spin.isotope) / 1e7))
495 file.write('%-8.3f' % (interatoms[0].r * 1e10))
496 file.write('%-8.3f\n' % (spin.csa * 1e6))
497
498 file.write('%-10s' % "vector")
499 file.write('%-4s' % atom1)
500 file.write('%-4s\n' % atom2)
501
502
504 """Create the script 'run.sh' for the execution of Modelfree4.
505
506 @param file: The writable file object.
507 @type file: file object
508 @keyword binary: The name of the Modelfree4 binary file. This can include the path to the
509 binary.
510 @type binary: str
511 @keyword dir: The directory to copy the PDB file to.
512 @type dir: str
513 """
514
515
516 if not hasattr(cdp, 'diff_tensor'):
517 raise RelaxNoTensorError('diffusion')
518
519 file.write("#! /bin/sh\n")
520 file.write(binary + " -i mfin -d mfdata -p mfpar -m mfmodel -o mfout -e out")
521 if cdp.diff_tensor.type != 'sphere':
522
523 mol = cdp.structure.structural_data[0].mol[0]
524 system('cp ' + mol.file_path + sep + mol.file_name + ' ' + dir)
525 file.write(" -s " + mol.file_name)
526 file.write("\n")
527
528
530 """Execute Modelfree4.
531
532 BUG: Control-C during execution causes the cwd to stay as dir.
533
534
535 @param dir: The optional directory where the script is located.
536 @type dir: str or None
537 @param force: A flag which if True will cause any pre-existing files to be overwritten by
538 Modelfree4.
539 @type force: bool
540 @param binary: The name of the Modelfree4 binary file. This can include the path to the
541 binary.
542 @type binary: str
543 """
544
545
546 if not hasattr(cdp, 'diff_tensor'):
547 raise RelaxNoTensorError('diffusion')
548
549
550 orig_dir = getcwd()
551
552
553 if dir == None:
554 dir = pipes.cdp_name()
555 if not access(dir, F_OK):
556 raise RelaxDirError('Modelfree4', dir)
557
558
559 chdir(dir)
560
561
562 try:
563
564 if Popen == None:
565 raise RelaxError("The subprocess module is not available in this version of Python.")
566
567
568 if not access('mfin', F_OK):
569 raise RelaxFileError('mfin input', 'mfin')
570
571
572 if not access('mfdata', F_OK):
573 raise RelaxFileError('mfdata input', 'mfdata')
574
575
576 if not access('mfmodel', F_OK):
577 raise RelaxFileError('mfmodel input', 'mfmodel')
578
579
580 if not access('mfpar', F_OK):
581 raise RelaxFileError('mfpar input', 'mfpar')
582
583
584 if cdp.diff_tensor.type != 'sphere':
585 pdb = cdp.structure.structural_data[0].mol[0].file_name
586 if not access(pdb, F_OK):
587 raise RelaxFileError('PDB', pdb)
588 else:
589 pdb = None
590
591
592 if force:
593 for file in listdir(getcwd()):
594 if search('out$', file) or search('rotate$', file):
595 remove(file)
596
597
598 test_binary(binary)
599
600
601 if pdb:
602 cmd = binary + ' -i mfin -d mfdata -p mfpar -m mfmodel -o mfout -e out -s ' + pdb
603 else:
604 cmd = binary + ' -i mfin -d mfdata -p mfpar -m mfmodel -o mfout -e out'
605 pipe = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=False)
606
607
608 pipe.stdin.close()
609
610
611 for line in pipe.stdout.readlines():
612
613 if hasattr(line, 'decode'):
614 line = line.decode()
615
616
617 sys.stdout.write(line)
618
619
620 for line in pipe.stderr.readlines():
621
622 if hasattr(line, 'decode'):
623 line = line.decode()
624
625
626 sys.stderr.write(line)
627
628
629 except:
630
631 chdir(orig_dir)
632
633
634 raise
635
636
637 chdir(orig_dir)
638
639
641 """Extract the Modelfree4 results out of the 'mfout' file.
642
643 @param dir: The directory containing the 'mfout' file.
644 @type dir: str or None
645 @keyword spin_id: The spin identification string.
646 @type spin_id: str or None
647 """
648
649
650 if not exists_mol_res_spin_data():
651 raise RelaxNoSequenceError
652
653
654 if not hasattr(cdp, 'diff_tensor'):
655 raise RelaxNoTensorError('diffusion')
656
657
658 if dir == None:
659 dir = pipes.cdp_name()
660 if not access(dir, F_OK):
661 raise RelaxDirError('Modelfree4', dir)
662
663
664 if not access(dir + sep+'mfout', F_OK):
665 raise RelaxFileError('Modelfree4', dir + sep+'mfout')
666
667
668 model_type = determine_model_type()
669
670
671 mfout_file = open(dir + sep+'mfout', 'r')
672 mfout_lines = mfout_file.readlines()
673 mfout_file.close()
674
675
676 global_chi2_pos, diff_pos, s2_pos, s2f_pos, s2s_pos, te_pos, rex_pos, chi2_pos = line_positions(mfout_lines)
677
678
679 sims = 0
680 for i in range(len(mfout_lines)):
681 if search('_iterations', mfout_lines[i]):
682 row = mfout_lines[i].split()
683 sims = int(row[1])
684
685
686 if model_type in ['all', 'diff']:
687
688 row = mfout_lines[global_chi2_pos].split()
689 cdp.chi2 = float(row[1])
690
691
692 if cdp.diff_tensor.type == 'sphere':
693
694 tm_row = mfout_lines[diff_pos].split()
695
696
697 cdp.diff_tensor.set(param='tm', value=float(tm_row[2]))
698
699
700 else:
701
702 tm_row = mfout_lines[diff_pos].split()
703 dratio_row = mfout_lines[diff_pos+1].split()
704 theta_row = mfout_lines[diff_pos+2].split()
705 phi_row = mfout_lines[diff_pos+3].split()
706
707
708 diffusion_tensor.set([float(tm_row[2]), float(dratio_row[2]), float(theta_row[2])*2.0*pi/360.0, float(phi_row[2])*2.0*pi/360.0], ['tm', 'Dratio', 'theta', 'phi'])
709
710
711 pos = 0
712 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
713
714 if not spin.select:
715 continue
716
717
718 mfout_res_num = int(mfout_lines[s2_pos + pos].split()[0])
719
720
721 if mfout_res_num != res_num:
722 continue
723
724
725 if not hasattr(spin, 'model'):
726 raise RelaxNoModelError
727
728
729 if 's2' in spin.params:
730 spin.s2, spin.s2_err = get_mf_data(mfout_lines, s2_pos + pos)
731
732
733 if 's2f' in spin.params or 's2s' in spin.params:
734 spin.s2f, spin.s2f_err = get_mf_data(mfout_lines, s2f_pos + pos)
735
736
737 if 's2f' in spin.params or 's2s' in spin.params:
738 spin.s2s, spin.s2s_err = get_mf_data(mfout_lines, s2s_pos + pos)
739
740
741 if 'te' in spin.params:
742 spin.te, spin.te_err = get_mf_data(mfout_lines, te_pos + pos)
743 spin.te = spin.te / 1e12
744 spin.te_err = spin.te_err / 1e12
745
746
747 if 'ts' in spin.params:
748 spin.ts, spin.ts_err = get_mf_data(mfout_lines, te_pos + pos)
749 spin.ts = spin.ts / 1e12
750 spin.ts_err = spin.ts_err / 1e12
751
752
753 if 'rex' in spin.params:
754 spin.rex, spin.rex_err = get_mf_data(mfout_lines, rex_pos + pos)
755 spin.rex = spin.rex / (2.0 * pi * cdp.spectrometer_frq[cdp.ri_ids[0]])**2
756 spin.rex_err = spin.rex_err / (2.0 * pi * cdp.spectrometer_frq[cdp.ri_ids[0]])**2
757
758
759 if not sims:
760 row = mfout_lines[chi2_pos + pos].split()
761 spin.chi2 = float(row[1])
762 else:
763
764 row = mfout_lines[chi2_pos + 2 + 22*pos].split()
765 spin.chi2 = float(row[1])
766
767
768 pos = pos + 1
769
770
772 """Extract the model-free data from the given position of the mfout file.
773
774 This method is designed to catch a number of bugs in Modelfree4's mfout file.
775
776 The first bug is the presence of a series of '*' characters causing a fusion of two columns.
777 This is handled by splitting by the '*' char and then returning the first element.
778
779 The second bug is when the floating point number is too big to fit into Modelfree4's string
780 format limit of 15.3f. This results in a results line such as:
781
782 246 10000.00019682363392.000 1 0.000 0.000 0.000 0.000
783
784 This is caught by scanning for two '.' characters in the column, and handled by assuming
785 that every floating point number will have three decimal characters.
786
787 @param mfout_lines: A list of all the lines of the mfout file.
788 @type mfout_lines: list of str
789 @param pos: The mfout line position.
790 @type pos: int
791 @return: The value and error.
792 @rtype: tuple of 2 floats
793 """
794
795
796 row = mfout_lines[pos].split()
797
798
799 val = row[1]
800 err = row[4]
801
802
803 if search('\*', val) or search('\*', err):
804
805 val_row = val.split('*')
806 err_row = err.split('*')
807
808
809 val = val_row[0]
810 err = err_row[0]
811
812
813 new_row = []
814 fused = False
815 for element in row:
816
817 num = element.count('.')
818
819
820 if num > 1:
821
822 fused = True
823
824
825 for i in range(num):
826
827 index = element.find('.')
828
829
830 new_row.append(element[0:index+4])
831
832
833 element = element[index+4:]
834
835
836 else:
837 new_row.append(element)
838
839
840 if fused:
841 val = new_row[1]
842 err = new_row[4]
843
844
845 return float(val), float(err)
846
847
849 """Function for getting the section positions (line number) of the mfout file.
850
851 @param mfout_lines: A list of all the lines of the mfout file.
852 @type mfout_lines: list of str
853 @return: The line indices where the s2, s2f, s2s, te, rex, and chi2 sections
854 start in the mfout file.
855 @rtype: tuple of int
856 """
857
858
859 i = 0
860 while i < len(mfout_lines):
861
862 if match('data_chi_square', mfout_lines[i]):
863 global_chi2_pos = i + 1
864
865
866 if match('data_diffusion_tensor', mfout_lines[i]):
867 diff_pos = i + 3
868
869
870 if match('data_model_1', mfout_lines[i]):
871
872 i = i + 2
873
874
875 while True:
876
877 if not mfout_lines[i] == '\n' and not search('^ ', mfout_lines[i]):
878 break
879
880
881 row = mfout_lines[i].split()
882
883
884 if len(row) == 2 and row[0] == 'S2':
885 s2_pos = i + 1
886
887
888 if len(row) == 2 and row[0] == 'S2f':
889 s2f_pos = i + 1
890
891
892 if len(row) == 2 and row[0] == 'S2s':
893 s2s_pos = i + 1
894
895
896 if len(row) == 2 and row[0] == 'te':
897 te_pos = i + 1
898
899
900 if len(row) == 2 and row[0] == 'Rex':
901 rex_pos = i + 1
902
903
904 i = i + 1
905
906
907 if match('data_sse', mfout_lines[i]):
908 chi2_pos = i + 3
909
910
911 i = i + 1
912
913
914 return global_chi2_pos, diff_pos, s2_pos, s2f_pos, s2s_pos, te_pos, rex_pos, chi2_pos
915