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