1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from os import F_OK, access, getcwd, listdir, sep
24 from re import search
25 from time import sleep
26
27
28 from float import floatAsByteArray
29 from info import Info_box; info = Info_box()
30 from generic_fns.interatomic import interatomic_loop
31 from generic_fns.mol_res_spin import exists_mol_res_spin_data, generate_spin_id, return_spin, spin_index_loop, spin_loop
32 from generic_fns.pipes import cdp_name, get_pipe, has_pipe, pipe_names, switch
33 from generic_fns import selection
34 from prompt.interpreter import Interpreter
35 from relax_errors import RelaxError, RelaxNoSequenceError, RelaxNoValueError
36 from relax_io import DummyFileObject
37 from relax_string import LIST, PARAGRAPH, SECTION, SUBSECTION, TITLE, to_docstring
38 from status import Status; status = Status()
39
40
41 doc = [
42 [TITLE, "Automatic analysis for black-box model-free results."],
43 [PARAGRAPH, "The dauvergne_protocol auto-analysis is designed for those who appreciate black-boxes or those who appreciate complex code. Importantly, data at multiple magnetic field strengths is essential for this analysis. If you would like to change how model-free analysis is performed, the code in the file auto_analyses/dauvergne_protocol.py in the base relax directory can be copied and modified as needed and used with the relax script interface. This file is simply a complex relax script. For a description of object-oriented coding in python using classes, functions/methods, self, etc., please see the python tutorial."],
44
45 [SECTION, "References"],
46
47 [SUBSECTION, "Auto-analysis primary reference"],
48 [PARAGRAPH, "The model-free optimisation methodology herein is that of:"],
49 [LIST, info.bib['dAuvergneGooley08b'].cite_short()],
50
51 [SUBSECTION, "Techniques used in the auto-analysis"],
52 [PARAGRAPH, "Other references for features of this dauvergne_protocol auto-analysis include model-free model selection using Akaike's Information Criterion:"],
53 [LIST, info.bib['dAuvergneGooley03'].cite_short()],
54 [PARAGRAPH, "The elimination of failed model-free models and Monte Carlo simulations:"],
55 [LIST, info.bib['dAuvergneGooley06'].cite_short()],
56 [PARAGRAPH, "Significant model-free optimisation improvements:"],
57 [LIST, info.bib['dAuvergneGooley08a'].cite_short()],
58 [PARAGRAPH, "Rather than searching for the lowest chi-squared value, this auto-analysis searches for the model with the lowest AIC criterion. This complex multi-universe, multi-dimensional problem is formulated, using set theory, as the universal solution:"],
59 [LIST, info.bib['dAuvergneGooley07'].cite_short()],
60 [PARAGRAPH, "The basic three references for the original and extended model-free theories are:"],
61 [LIST, info.bib['LipariSzabo82a'].cite_short()],
62 [LIST, info.bib['LipariSzabo82b'].cite_short()],
63 [LIST, info.bib['Clore90'].cite_short()],
64
65 [SECTION, "How to use this auto-analysis"],
66 [PARAGRAPH, "The five diffusion models used in this auto-analysis are:"],
67 [LIST, "Model I (MI) - Local tm."],
68 [LIST, "Model II (MII) - Sphere."],
69 [LIST, "Model III (MIII) - Prolate spheroid."],
70 [LIST, "Model IV (MIV) - Oblate spheroid."],
71 [LIST, "Model V (MV) - Ellipsoid."],
72 [PARAGRAPH, "If using the script-based user interface (UI), changing the value of the variable diff_model will determine the behaviour of this auto-analysis. Model I must be optimised prior to any of the other diffusion models, while the Models II to V can be optimised in any order. To select the various models, set the variable diff_model to the following strings:"],
73 [LIST, "MI - 'local_tm'"],
74 [LIST, "MII - 'sphere'"],
75 [LIST, "MIII - 'prolate'"],
76 [LIST, "MIV - 'oblate'"],
77 [LIST, "MV - 'ellipsoid'"],
78 [PARAGRAPH, "This approach has the advantage of eliminating the need for an initial estimate of a global diffusion tensor and removing all the problems associated with the initial estimate."],
79 [PARAGRAPH, "It is important that the number of parameters in a model does not exceed the number of relaxation data sets for that spin. If this is the case, the list of models in the mf_models and local_tm_models variables will need to be trimmed."],
80
81 [SUBSECTION, "Model I - Local tm"],
82 [PARAGRAPH, "This will optimise the diffusion model whereby all spin of the molecule have a local tm value, i.e. there is no global diffusion tensor. This model needs to be optimised prior to optimising any of the other diffusion models. Each spin is fitted to the multiple model-free models separately, where the parameter tm is included in each model."],
83 [PARAGRAPH, "AIC model selection is used to select the models for each spin."],
84
85 [SUBSECTION, "Model II - Sphere"],
86 [PARAGRAPH, "This will optimise the isotropic diffusion model. Multiple steps are required, an initial optimisation of the diffusion tensor, followed by a repetitive optimisation until convergence of the diffusion tensor. In the relax script UI each of these steps requires this script to be rerun, unless the conv_loop flag is True. In the GUI (graphical user interface), the procedure is repeated automatically until convergence. For the initial optimisation, which will be placed in the directory './sphere/init/', the following steps are used:"],
87 [PARAGRAPH, "The model-free models and parameter values for each spin are set to those of diffusion model MI."],
88 [PARAGRAPH, "The local tm parameter is removed from the models."],
89 [PARAGRAPH, "The model-free parameters are fixed and a global spherical diffusion tensor is minimised."],
90 [PARAGRAPH, "For the repetitive optimisation, each minimisation is named from 'round_1' onwards. The initial 'round_1' optimisation will extract the diffusion tensor from the results file in './sphere/init/', and the results will be placed in the directory './sphere/round_1/'. Each successive round will take the diffusion tensor from the previous round. The following steps are used:"],
91 [PARAGRAPH, "The global diffusion tensor is fixed and the multiple model-free models are fitted to each spin."],
92 [PARAGRAPH, "AIC model selection is used to select the models for each spin."],
93 [PARAGRAPH, "All model-free and diffusion parameters are allowed to vary and a global optimisation of all parameters is carried out."],
94
95 [SUBSECTION, "Model III - Prolate spheroid"],
96 [PARAGRAPH, "The methods used are identical to those of diffusion model MII, except that an axially symmetric diffusion tensor with Da >= 0 is used. The base directory containing all the results is './prolate/'."],
97
98 [SUBSECTION, "Model IV - Oblate spheroid"],
99 [PARAGRAPH, "The methods used are identical to those of diffusion model MII, except that an axially symmetric diffusion tensor with Da <= 0 is used. The base directory containing all the results is './oblate/'."],
100
101 [SUBSECTION, "Model V - Ellipsoid"],
102 [PARAGRAPH, "The methods used are identical to those of diffusion model MII, except that a fully anisotropic diffusion tensor is used (also known as rhombic or asymmetric diffusion). The base directory is './ellipsoid/'."],
103
104 [SUBSECTION, "Final run"],
105 [PARAGRAPH, "Once all the diffusion models have converged, the final run can be executed. This is done by setting the variable diff_model to 'final'. This consists of two steps, diffusion tensor model selection, and Monte Carlo simulations. Firstly AIC model selection is used to select between the diffusion tensor models. Monte Carlo simulations are then run solely on this selected diffusion model. Minimisation of the model is bypassed as it is assumed that the model is already fully optimised (if this is not the case the final run is not yet appropriate)."],
106 [PARAGRAPH, "The final black-box model-free results will be placed in the file 'final/results'."]
107 ]
108
109
110
111 __doc__ = to_docstring(doc)
112
113
114
116 """The model-free auto-analysis."""
117
118
119 opt_func_tol = 1e-25
120 opt_max_iterations = int(1e7)
121
122 - def __init__(self, pipe_name=None, pipe_bundle=None, results_dir=None, diff_model=None, mf_models=['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9'], local_tm_models=['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9'], grid_inc=11, diff_tensor_grid_inc={'sphere': 11, 'prolate': 11, 'oblate': 11, 'ellipsoid': 6}, min_algor='newton', mc_sim_num=500, max_iter=None, user_fns=None, conv_loop=True):
123 """Perform the full model-free analysis protocol of d'Auvergne and Gooley, 2008b.
124
125 @keyword pipe_name: The name of the data pipe containing the sequence info. This data pipe should have all values set including the CSA value, the bond length, the heteronucleus name and proton name. It should also have all relaxation data loaded.
126 @type pipe_name: str
127 @keyword pipe_bundle: The data pipe bundle to associate all spawned data pipes with.
128 @type pipe_bundle: str
129 @keyword results_dir: The directory, where files are saved in.
130 @type results_dir: str
131 @keyword diff_model: The global diffusion model to optimise. This can be one of 'local_tm', 'sphere', 'oblate', 'prolate', 'ellipsoid', or 'final'. If all or a subset of these are supplied as a list, then these will be automatically looped over and calculated.
132 @type diff_model: str or list of str
133 @keyword mf_models: The model-free models.
134 @type mf_models: list of str
135 @keyword local_tm_models: The model-free models.
136 @type local_tm_models: list of str
137 @keyword grid_inc: The grid search size (the number of increments per dimension).
138 @type grid_inc: int
139 @keyword diff_tensor_grid_inc: A list of grid search sizes for the optimisation of the sphere, prolate spheroid, oblate spheroid, and ellipsoid.
140 @type diff_tensor_grid_inc: list of int
141 @keyword min_algor: The minimisation algorithm (in most cases this should not be changed).
142 @type min_algor: str
143 @keyword mc_sim_num: The number of Monte Carlo simulations to be used for error analysis at the end of the analysis.
144 @type mc_sim_num: int
145 @keyword max_iter: The maximum number of iterations for the global iteration. Set to None, then the algorithm iterates until convergence.
146 @type max_iter: int or None.
147 @keyword user_fns: A dictionary of replacement user functions. These will overwrite the standard user functions. The key should be the name of the user function or user function class and the value should be the function or class instance.
148 @type user_fns: dict
149 @keyword conv_loop: Automatic looping over all rounds until convergence.
150 @type conv_loop: bool
151 """
152
153
154 status.exec_lock.acquire(pipe_bundle, mode='auto-analysis')
155
156
157 self.pipe_name = pipe_name
158 self.pipe_bundle = pipe_bundle
159 self.mf_models = mf_models
160 self.local_tm_models = local_tm_models
161 self.grid_inc = grid_inc
162 self.diff_tensor_grid_inc = diff_tensor_grid_inc
163 self.min_algor = min_algor
164 self.mc_sim_num = mc_sim_num
165 self.max_iter = max_iter
166 self.conv_loop = conv_loop
167
168
169 self.mf_model_pipes = []
170 for i in range(len(self.mf_models)):
171 self.mf_model_pipes.append(self.name_pipe(self.mf_models[i]))
172 self.local_tm_model_pipes = []
173 for i in range(len(self.local_tm_models)):
174 self.local_tm_model_pipes.append(self.name_pipe(self.local_tm_models[i]))
175
176
177 if isinstance(diff_model, list):
178 self.diff_model_list = diff_model
179 else:
180 self.diff_model_list = [diff_model]
181
182
183 if results_dir:
184 self.results_dir = results_dir + sep
185 else:
186 self.results_dir = getcwd() + sep
187
188
189 self.check_vars()
190
191
192 if self.pipe_name != cdp_name():
193 switch(self.pipe_name)
194
195
196 self.status_setup()
197
198
199 self.interpreter = Interpreter(show_script=False, quit=False, raise_relax_error=True)
200 self.interpreter.populate_self()
201 self.interpreter.on(verbose=False)
202
203
204 if user_fns:
205 for name in user_fns:
206 setattr(self.interpreter, name, user_fns[name])
207
208
209 try:
210
211 for self.diff_model in self.diff_model_list:
212
213 sleep(1)
214
215
216 status.auto_analysis[self.pipe_bundle].diff_model = self.diff_model
217
218
219 self.conv_data = Container()
220 self.conv_data.chi2 = []
221 self.conv_data.models = []
222 self.conv_data.diff_vals = []
223 if self.diff_model == 'sphere':
224 self.conv_data.diff_params = ['tm']
225 elif self.diff_model == 'oblate' or self.diff_model == 'prolate':
226 self.conv_data.diff_params = ['tm', 'Da', 'theta', 'phi']
227 elif self.diff_model == 'ellipsoid':
228 self.conv_data.diff_params = ['tm', 'Da', 'Dr', 'alpha', 'beta', 'gamma']
229 self.conv_data.spin_ids = []
230 self.conv_data.mf_params = []
231 self.conv_data.mf_vals = []
232
233
234 self.execute()
235
236
237 finally:
238
239 status.auto_analysis[self.pipe_bundle].fin = True
240 status.current_analysis = None
241 status.exec_lock.release()
242
243
245 """Check that the user has set the variables correctly."""
246
247
248 if not isinstance(self.pipe_bundle, str):
249 raise RelaxError("The pipe bundle name '%s' is invalid." % self.pipe_bundle)
250
251
252 valid_models = ['local_tm', 'sphere', 'oblate', 'prolate', 'ellipsoid', 'final']
253 for i in range(len(self.diff_model_list)):
254 if self.diff_model_list[i] not in valid_models:
255 raise RelaxError("The diff_model value '%s' is incorrectly set. It must be one of %s." % (self.diff_model_list[i], valid_models))
256
257
258 mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9']
259 local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9']
260 if not isinstance(self.mf_models, list):
261 raise RelaxError("The self.mf_models user variable must be a list.")
262 if not isinstance(self.local_tm_models, list):
263 raise RelaxError("The self.local_tm_models user variable must be a list.")
264 for i in range(len(self.mf_models)):
265 if self.mf_models[i] not in mf_models:
266 raise RelaxError("The self.mf_models user variable '%s' is incorrectly set. It must be one of %s." % (self.mf_models, mf_models))
267 for i in range(len(self.local_tm_models)):
268 if self.local_tm_models[i] not in local_tm_models:
269 raise RelaxError("The self.local_tm_models user variable '%s' is incorrectly set. It must be one of %s." % (self.local_tm_models, local_tm_models))
270
271
272 if not exists_mol_res_spin_data():
273 raise RelaxNoSequenceError(self.pipe_name)
274
275
276 if not hasattr(cdp, 'ri_ids') or len(cdp.ri_ids) == 0:
277 raise RelaxNoRiError(ri_id)
278
279
280 if len(cdp.ri_ids) <= 3:
281 raise RelaxError("Insufficient relaxation data, 4 or more data sets are essential for the execution of this script.")
282
283
284 for spin, spin_id in spin_loop(return_id=True):
285
286 if not spin.select:
287 continue
288
289
290 if not hasattr(spin, 'isotope') or spin.isotope == None:
291 raise RelaxNoValueError("nuclear isotope type", spin_id=spin_id)
292
293
294 if not hasattr(spin, 'ri_data') or spin.ri_data == None:
295 continue
296
297
298 if not hasattr(spin, 'csa') or spin.csa == None:
299 raise RelaxNoValueError("CSA", spin_id=spin_id)
300
301
302 for interatom in interatomic_loop():
303
304 spin1 = return_spin(interatom.spin_id1)
305 spin2 = return_spin(interatom.spin_id2)
306
307
308 if not spin1.select or not spin2.select:
309 continue
310
311
312 if not hasattr(interatom, 'r') or interatom.r == None:
313 raise RelaxNoValueError("interatomic distance", spin_id=interatom.spin_id1, spin_id2=interatom.spin_id2)
314
315
316 if not isinstance(self.grid_inc, int):
317 raise RelaxError("The grid_inc user variable '%s' is incorrectly set. It should be an integer." % self.grid_inc)
318 if not isinstance(self.diff_tensor_grid_inc, dict):
319 raise RelaxError("The diff_tensor_grid_inc user variable '%s' is incorrectly set. It should be a dictionary." % self.diff_tensor_grid_inc)
320 for tensor in ['sphere', 'prolate', 'oblate', 'ellipsoid']:
321 if not tensor in self.diff_tensor_grid_inc:
322 raise RelaxError("The diff_tensor_grid_inc user variable '%s' is incorrectly set. It should contain the '%s' key." % (self.diff_tensor_grid_inc, tensor))
323 if not isinstance(self.diff_tensor_grid_inc[tensor], int):
324 raise RelaxError("The diff_tensor_grid_inc user variable '%s' is incorrectly set. The value corresponding to the key '%s' should be an integer." % (self.diff_tensor_grid_inc, tensor))
325 if not isinstance(self.min_algor, str):
326 raise RelaxError("The min_algor user variable '%s' is incorrectly set. It should be a string." % self.min_algor)
327 if not isinstance(self.mc_sim_num, int):
328 raise RelaxError("The mc_sim_num user variable '%s' is incorrectly set. It should be an integer." % self.mc_sim_num)
329
330
331 if not isinstance(self.conv_loop, bool):
332 raise RelaxError("The conv_loop user variable '%s' is incorrectly set. It should be one of the booleans True or False." % self.conv_loop)
333
334
336 """Test for the convergence of the global model."""
337
338
339 print("\n\n\n")
340 print("#####################")
341 print("# Convergence tests #")
342 print("#####################\n")
343
344
345 if self.max_iter and self.round > self.max_iter:
346 print("Maximum number of global iterations reached. Terminating the protocol before convergence has been reached.")
347 return True
348
349
350 self.conv_data.chi2.append(cdp.chi2)
351
352
353 curr_models = ''
354 for spin in spin_loop():
355 if hasattr(spin, 'model'):
356 if not spin.model == 'None':
357 curr_models = curr_models + spin.model
358 self.conv_data.models.append(curr_models)
359
360
361 self.conv_data.diff_vals.append([])
362 for param in self.conv_data.diff_params:
363
364 self.conv_data.diff_vals[-1].append(getattr(cdp.diff_tensor, param))
365
366
367 self.conv_data.mf_vals.append([])
368 self.conv_data.mf_params.append([])
369 self.conv_data.spin_ids.append([])
370 for spin, spin_id in spin_loop(return_id=True):
371
372 if not hasattr(spin, 'params'):
373 continue
374
375
376 self.conv_data.spin_ids[-1].append(spin_id)
377 self.conv_data.mf_params[-1].append([])
378 self.conv_data.mf_vals[-1].append([])
379
380
381 for j in range(len(spin.params)):
382
383 self.conv_data.mf_params[-1][-1].append(spin.params[j])
384 self.conv_data.mf_vals[-1][-1].append(getattr(spin, spin.params[j].lower()))
385
386
387 if self.round == 1:
388 print("First round of optimisation, skipping the convergence tests.\n\n\n")
389 return False
390
391
392 converged = False
393 for i in range(self.start_round, self.round - 1):
394
395 print("\n\n\n# Comparing the current iteration to iteration %i.\n" % (i+1))
396
397
398 index = i - self.start_round
399
400
401 print("Chi-squared test:")
402 print(" chi2 (iter %i): %s" % (i+1, self.conv_data.chi2[index]))
403 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.chi2[index]))
404 print(" chi2 (iter %i): %s" % (self.round, self.conv_data.chi2[-1]))
405 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.chi2[-1]))
406 print(" chi2 (difference): %s" % (self.conv_data.chi2[index] - self.conv_data.chi2[-1]))
407 if self.conv_data.chi2[index] == self.conv_data.chi2[-1]:
408 print(" The chi-squared value has converged.\n")
409 else:
410 print(" The chi-squared value has not converged.\n")
411 continue
412
413
414 print("Identical model-free models test:")
415 if self.conv_data.models[index] == self.conv_data.models[-1]:
416 print(" The model-free models have converged.\n")
417 else:
418 print(" The model-free models have not converged.\n")
419 continue
420
421
422 print("Identical diffusion tensor parameter test:")
423 params_converged = True
424 for k in range(len(self.conv_data.diff_params)):
425
426 if self.conv_data.diff_vals[index][k] != self.conv_data.diff_vals[-1][k]:
427 print(" Parameter: %s" % param)
428 print(" Value (iter %i): %s" % (i+1, self.conv_data.diff_vals[index][k]))
429 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.diff_vals[index][k]))
430 print(" Value (iter %i): %s" % (self.round, self.conv_data.diff_vals[-1][k]))
431 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.diff_vals[-1][k]))
432 print(" The diffusion parameters have not converged.\n")
433 params_converged = False
434 break
435 if not params_converged:
436 continue
437 print(" The diffusion tensor parameters have converged.\n")
438
439
440 print("\nIdentical model-free parameter test:")
441 if len(self.conv_data.spin_ids[index]) != len(self.conv_data.spin_ids[-1]):
442 print(" Different number of spins.")
443 continue
444 for j in range(len(self.conv_data.spin_ids[-1])):
445
446 for k in range(len(self.conv_data.mf_params[-1][j])):
447
448 if self.conv_data.mf_vals[index][j][k] != self.conv_data.mf_vals[-1][j][k]:
449 print(" Spin ID: %s" % self.conv_data.spin_ids[-1][j])
450 print(" Parameter: %s" % self.conv_data.mf_params[-1][j][k])
451 print(" Value (iter %i): %s" % (i+1, self.conv_data.mf_vals[index][j][k]))
452 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.mf_vals[index][j][k]))
453 print(" Value (iter %i): %s" % (self.round, self.conv_data.mf_vals[-1][j][k]))
454 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.mf_vals[index][j][k]))
455 print(" The model-free parameters have not converged.\n")
456 params_converged = False
457 break
458 if not params_converged:
459 continue
460 print(" The model-free parameters have converged.\n")
461
462
463 converged = True
464 break
465
466
467
468
469
470 print("\nConvergence:")
471 if converged:
472
473 status.auto_analysis[self.pipe_bundle].convergence = True
474
475
476 print(" [ Yes ]")
477
478
479 return True
480 else:
481
482 print(" [ No ]")
483
484
485 return False
486
487
489 """Function for returning the name of next round of optimisation."""
490
491
492 try:
493 dir_list = listdir(self.results_dir+sep+model)
494 except:
495 return 0
496
497
498 if 'init' not in dir_list:
499 return 0
500
501
502 rnd_dirs = []
503 for file in dir_list:
504 if search('^round_', file):
505 rnd_dirs.append(file)
506
507
508 numbers = []
509 for dir in rnd_dirs:
510 try:
511 numbers.append(int(dir[6:]))
512 except:
513 pass
514 numbers.sort()
515
516
517 if not len(numbers):
518 return 1
519
520
521 max_round = numbers[-1]
522
523
524 for i in range(max_round, -1, -1):
525
526 complete_round = i
527
528
529 file_root = self.results_dir + sep + model + sep + "round_%i" % i + sep + 'opt' + sep + 'results'
530
531
532 if access(file_root + '.bz2', F_OK):
533 break
534 if access(file_root + '.gz', F_OK):
535 break
536 if access(file_root, F_OK):
537 break
538
539
540 if complete_round == 0:
541 return 0
542
543
544 return complete_round + 1
545
546
548 """Execute the protocol."""
549
550
551
552
553 if self.diff_model == 'local_tm':
554
555 self.base_dir = self.results_dir+'local_tm'+sep
556
557
558 self.multi_model(local_tm=True)
559
560
561 self.model_selection(modsel_pipe=self.name_pipe('aic'), dir=self.base_dir + 'aic')
562
563
564
565
566
567 elif self.diff_model == 'sphere' or self.diff_model == 'prolate' or self.diff_model == 'oblate' or self.diff_model == 'ellipsoid':
568
569 dir_list = listdir(self.results_dir)
570 if 'local_tm' not in dir_list:
571 raise RelaxError("The local_tm model must be optimised first.")
572
573
574 self.start_round = self.determine_rnd(model=self.diff_model)
575
576
577
578 while True:
579
580 self.round = self.determine_rnd(model=self.diff_model)
581 status.auto_analysis[self.pipe_bundle].round = self.round
582
583
584 if self.round == 0:
585
586 self.base_dir = self.results_dir+self.diff_model+sep+'init'+sep
587
588
589 name = self.name_pipe(self.diff_model)
590
591
592 if has_pipe(name):
593 self.interpreter.pipe.delete(name)
594 self.interpreter.pipe.create(name, 'mf', bundle=self.pipe_bundle)
595
596
597 self.interpreter.results.read(file='results', dir=self.results_dir+'local_tm'+sep+'aic')
598
599
600 self.interpreter.model_free.remove_tm()
601
602
603 if self.diff_model == 'sphere':
604 self.interpreter.diffusion_tensor.init(10e-9, fixed=False)
605 inc = self.diff_tensor_grid_inc['sphere']
606 elif self.diff_model == 'prolate':
607 self.interpreter.diffusion_tensor.init((10e-9, 0, 0, 0), spheroid_type='prolate', fixed=False)
608 inc = self.diff_tensor_grid_inc['prolate']
609 elif self.diff_model == 'oblate':
610 self.interpreter.diffusion_tensor.init((10e-9, 0, 0, 0), spheroid_type='oblate', fixed=False)
611 inc = self.diff_tensor_grid_inc['oblate']
612 elif self.diff_model == 'ellipsoid':
613 self.interpreter.diffusion_tensor.init((10e-09, 0, 0, 0, 0, 0), fixed=False)
614 inc = self.diff_tensor_grid_inc['ellipsoid']
615
616
617 self.interpreter.fix('all_spins')
618 self.interpreter.grid_search(inc=inc)
619 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
620
621
622 self.interpreter.results.write(file='results', dir=self.base_dir, force=True)
623
624
625
626 else:
627
628 self.base_dir = self.results_dir+self.diff_model + sep+'round_'+repr(self.round)+sep
629
630
631 self.load_tensor()
632
633
634 self.multi_model()
635
636
637 self.model_selection(modsel_pipe=self.name_pipe('aic'), dir=self.base_dir + 'aic')
638
639
640 self.interpreter.fix('all', fixed=False)
641
642
643 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
644
645
646 dir = self.base_dir + 'opt'
647 self.interpreter.results.write(file='results', dir=dir, force=True)
648
649
650 converged = self.convergence()
651
652
653 if converged or not self.conv_loop:
654 break
655
656
657 status.auto_analysis[self.pipe_bundle].round = None
658
659
660
661
662
663 elif self.diff_model == 'final':
664
665
666
667
668 models = ['local_tm', 'sphere', 'prolate', 'oblate', 'ellipsoid']
669 self.pipes = []
670 for name in models:
671 self.pipes.append(self.name_pipe(name))
672
673
674 for name in pipe_names(bundle=self.pipe_bundle):
675 if name in self.pipes + self.mf_model_pipes + self.local_tm_model_pipes + [self.name_pipe('aic'), self.name_pipe('previous')]:
676 self.interpreter.pipe.delete(name)
677
678
679 dir_list = listdir(self.results_dir)
680 for name in models:
681 if name not in dir_list:
682 raise RelaxError("The %s model must be optimised first." % name)
683
684
685 self.interpreter.pipe.create(self.name_pipe('local_tm'), 'mf', bundle=self.pipe_bundle)
686
687
688 self.interpreter.results.read(file='results', dir=self.results_dir+'local_tm'+sep+'aic')
689
690
691 for model in ['sphere', 'prolate', 'oblate', 'ellipsoid']:
692
693 self.round = self.determine_rnd(model=model) - 1
694
695
696 if self.round < 1:
697
698 name = model
699 if model == 'prolate' or model == 'oblate':
700 name = name + ' spheroid'
701
702
703 raise RelaxError("Multiple rounds of optimisation of the " + name + " (between 8 to 15) are required for the proper execution of this script.")
704
705
706 self.interpreter.pipe.create(self.name_pipe(model), 'mf', bundle=self.pipe_bundle)
707
708
709 self.interpreter.results.read(file='results', dir=self.results_dir+model + sep+'round_'+repr(self.round)+sep+'opt')
710
711
712 self.model_selection(modsel_pipe=self.name_pipe('final'), write_flag=False)
713
714
715
716
717
718
719 if hasattr(get_pipe(self.name_pipe('final')), 'diff_tensor'):
720 self.interpreter.fix('diff')
721
722
723 self.interpreter.monte_carlo.setup(number=self.mc_sim_num)
724 self.interpreter.monte_carlo.create_data()
725 self.interpreter.monte_carlo.initial_values()
726 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
727 self.interpreter.eliminate()
728 self.interpreter.monte_carlo.error_analysis()
729
730
731
732
733
734
735 self.write_results()
736
737
738
739
740
741 else:
742 raise RelaxError("Unknown diffusion model, change the value of 'self.diff_model'")
743
744
760
761
773
774
820
821
823 """Generate a unique name for the data pipe.
824
825 @param prefix: The prefix of the data pipe name.
826 @type prefix: str
827 """
828
829
830 name = "%s - %s" % (prefix, self.pipe_bundle)
831
832
833 return name
834
835
863
864
866 """Create Grace plots of the final model-free results."""
867
868
869 dir = self.results_dir + 'final'
870 self.interpreter.results.write(file='results', dir=dir, force=True)
871
872
873 dir = self.results_dir + 'final' + sep + 'grace'
874 self.interpreter.grace.write(x_data_type='spin', y_data_type='s2', file='s2.agr', dir=dir, force=True)
875 self.interpreter.grace.write(x_data_type='spin', y_data_type='s2f', file='s2f.agr', dir=dir, force=True)
876 self.interpreter.grace.write(x_data_type='spin', y_data_type='s2s', file='s2s.agr', dir=dir, force=True)
877 self.interpreter.grace.write(x_data_type='spin', y_data_type='te', file='te.agr', dir=dir, force=True)
878 self.interpreter.grace.write(x_data_type='spin', y_data_type='tf', file='tf.agr', dir=dir, force=True)
879 self.interpreter.grace.write(x_data_type='spin', y_data_type='ts', file='ts.agr', dir=dir, force=True)
880 self.interpreter.grace.write(x_data_type='spin', y_data_type='rex', file='rex.agr', dir=dir, force=True)
881 self.interpreter.grace.write(x_data_type='s2', y_data_type='te', file='s2_vs_te.agr', dir=dir, force=True)
882 self.interpreter.grace.write(x_data_type='s2', y_data_type='rex', file='s2_vs_rex.agr', dir=dir, force=True)
883 self.interpreter.grace.write(x_data_type='te', y_data_type='rex', file='te_vs_rex.agr', dir=dir, force=True)
884
885
886 dir = self.results_dir + 'final'
887 self.interpreter.value.write(param='s2', file='s2.txt', dir=dir, force=True)
888 self.interpreter.value.write(param='s2f', file='s2f.txt', dir=dir, force=True)
889 self.interpreter.value.write(param='s2s', file='s2s.txt', dir=dir, force=True)
890 self.interpreter.value.write(param='te', file='te.txt', dir=dir, force=True)
891 self.interpreter.value.write(param='tf', file='tf.txt', dir=dir, force=True)
892 self.interpreter.value.write(param='ts', file='ts.txt', dir=dir, force=True)
893 self.interpreter.value.write(param='rex', file='rex.txt', dir=dir, force=True)
894 self.interpreter.value.write(param='local_tm', file='local_tm.txt', dir=dir, force=True)
895
896
897 dir = self.results_dir + 'final' + sep + 'pymol'
898 self.interpreter.pymol.macro_write(data_type='s2', dir=dir, force=True)
899 self.interpreter.pymol.macro_write(data_type='s2f', dir=dir, force=True)
900 self.interpreter.pymol.macro_write(data_type='s2s', dir=dir, force=True)
901 self.interpreter.pymol.macro_write(data_type='amp_fast', dir=dir, force=True)
902 self.interpreter.pymol.macro_write(data_type='amp_slow', dir=dir, force=True)
903 self.interpreter.pymol.macro_write(data_type='te', dir=dir, force=True)
904 self.interpreter.pymol.macro_write(data_type='tf', dir=dir, force=True)
905 self.interpreter.pymol.macro_write(data_type='ts', dir=dir, force=True)
906 self.interpreter.pymol.macro_write(data_type='time_fast', dir=dir, force=True)
907 self.interpreter.pymol.macro_write(data_type='time_slow', dir=dir, force=True)
908 self.interpreter.pymol.macro_write(data_type='rex', dir=dir, force=True)
909
910
911 dir = self.results_dir + 'final' + sep + 'molmol'
912 self.interpreter.molmol.macro_write(data_type='s2', dir=dir, force=True)
913 self.interpreter.molmol.macro_write(data_type='s2f', dir=dir, force=True)
914 self.interpreter.molmol.macro_write(data_type='s2s', dir=dir, force=True)
915 self.interpreter.molmol.macro_write(data_type='amp_fast', dir=dir, force=True)
916 self.interpreter.molmol.macro_write(data_type='amp_slow', dir=dir, force=True)
917 self.interpreter.molmol.macro_write(data_type='te', dir=dir, force=True)
918 self.interpreter.molmol.macro_write(data_type='tf', dir=dir, force=True)
919 self.interpreter.molmol.macro_write(data_type='ts', dir=dir, force=True)
920 self.interpreter.molmol.macro_write(data_type='time_fast', dir=dir, force=True)
921 self.interpreter.molmol.macro_write(data_type='time_slow', dir=dir, force=True)
922 self.interpreter.molmol.macro_write(data_type='rex', dir=dir, force=True)
923
924
925 dir = self.results_dir + 'final'
926 self.interpreter.structure.create_diff_tensor_pdb(file="tensor.pdb", dir=dir, force=True)
927
928
929
931 """Empty container for data storage."""
932