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, access, getcwd, listdir, sep
25 from re import search
26 from time import sleep
27
28
29 from lib.float import floatAsByteArray
30 from info import Info_box; info = Info_box()
31 from pipe_control.interatomic import interatomic_loop
32 from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop
33 from pipe_control.pipes import cdp_name, get_pipe, has_pipe, pipe_names, switch
34 from pipe_control import spectrometer
35 from prompt.interpreter import Interpreter
36 from lib.errors import RelaxError, RelaxNoSequenceError, RelaxNoValueError
37 from lib.text.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, write_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 optimisation results will read from. Results will also be saved to this directory if the write_results_dir argument is not given.
130 @type results_dir: str
131 @keyword write_results_dir: The directory where optimisation results will be saved in. If None, it will default to the value of the results_dir argument. This is mainly used for debugging.
132 @type write_results_dir: str or None
133 @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.
134 @type diff_model: str or list of str
135 @keyword mf_models: The model-free models.
136 @type mf_models: list of str
137 @keyword local_tm_models: The model-free models.
138 @type local_tm_models: list of str
139 @keyword grid_inc: The grid search size (the number of increments per dimension).
140 @type grid_inc: int
141 @keyword diff_tensor_grid_inc: A list of grid search sizes for the optimisation of the sphere, prolate spheroid, oblate spheroid, and ellipsoid.
142 @type diff_tensor_grid_inc: list of int
143 @keyword min_algor: The minimisation algorithm (in most cases this should not be changed).
144 @type min_algor: str
145 @keyword mc_sim_num: The number of Monte Carlo simulations to be used for error analysis at the end of the analysis.
146 @type mc_sim_num: int
147 @keyword max_iter: The maximum number of iterations for the global iteration. Set to None, then the algorithm iterates until convergence.
148 @type max_iter: int or None.
149 @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.
150 @type user_fns: dict
151 @keyword conv_loop: Automatic looping over all rounds until convergence.
152 @type conv_loop: bool
153 """
154
155
156 status.exec_lock.acquire(pipe_bundle, mode='auto-analysis')
157
158
159 self.pipe_name = pipe_name
160 self.pipe_bundle = pipe_bundle
161 self.mf_models = mf_models
162 self.local_tm_models = local_tm_models
163 self.grid_inc = grid_inc
164 self.diff_tensor_grid_inc = diff_tensor_grid_inc
165 self.min_algor = min_algor
166 self.mc_sim_num = mc_sim_num
167 self.max_iter = max_iter
168 self.conv_loop = conv_loop
169
170
171 self.mf_model_pipes = []
172 for i in range(len(self.mf_models)):
173 self.mf_model_pipes.append(self.name_pipe(self.mf_models[i]))
174 self.local_tm_model_pipes = []
175 for i in range(len(self.local_tm_models)):
176 self.local_tm_model_pipes.append(self.name_pipe(self.local_tm_models[i]))
177
178
179 if isinstance(diff_model, list):
180 self.diff_model_list = diff_model
181 else:
182 self.diff_model_list = [diff_model]
183
184
185 if results_dir:
186 self.results_dir = results_dir + sep
187 else:
188 self.results_dir = getcwd() + sep
189 if write_results_dir:
190 self.write_results_dir = write_results_dir + sep
191 else:
192 self.write_results_dir = self.results_dir
193
194
195 self.check_vars()
196
197
198 if self.pipe_name != cdp_name():
199 switch(self.pipe_name)
200
201
202 self.status_setup()
203
204
205 self.interpreter = Interpreter(show_script=False, raise_relax_error=True)
206 self.interpreter.populate_self()
207 self.interpreter.on(verbose=False)
208
209
210 if user_fns:
211 for name in user_fns:
212 setattr(self.interpreter, name, user_fns[name])
213
214
215 try:
216
217 for self.diff_model in self.diff_model_list:
218
219 sleep(1)
220
221
222 status.auto_analysis[self.pipe_bundle].diff_model = self.diff_model
223
224
225 self.conv_data = Container()
226 self.conv_data.chi2 = []
227 self.conv_data.models = []
228 self.conv_data.diff_vals = []
229 if self.diff_model == 'sphere':
230 self.conv_data.diff_params = ['tm']
231 elif self.diff_model == 'oblate' or self.diff_model == 'prolate':
232 self.conv_data.diff_params = ['tm', 'Da', 'theta', 'phi']
233 elif self.diff_model == 'ellipsoid':
234 self.conv_data.diff_params = ['tm', 'Da', 'Dr', 'alpha', 'beta', 'gamma']
235 self.conv_data.spin_ids = []
236 self.conv_data.mf_params = []
237 self.conv_data.mf_vals = []
238
239
240 self.execute()
241
242
243 finally:
244
245 status.auto_analysis[self.pipe_bundle].fin = True
246 status.current_analysis = None
247 status.exec_lock.release()
248
249
251 """Check that the user has set the variables correctly."""
252
253
254 if not isinstance(self.pipe_bundle, str):
255 raise RelaxError("The pipe bundle name '%s' is invalid." % self.pipe_bundle)
256
257
258 valid_models = ['local_tm', 'sphere', 'oblate', 'prolate', 'ellipsoid', 'final']
259 for i in range(len(self.diff_model_list)):
260 if self.diff_model_list[i] not in valid_models:
261 raise RelaxError("The diff_model value '%s' is incorrectly set. It must be one of %s." % (self.diff_model_list[i], valid_models))
262
263
264 mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9']
265 local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9']
266 if not isinstance(self.mf_models, list):
267 raise RelaxError("The self.mf_models user variable must be a list.")
268 if not isinstance(self.local_tm_models, list):
269 raise RelaxError("The self.local_tm_models user variable must be a list.")
270 for i in range(len(self.mf_models)):
271 if self.mf_models[i] not in mf_models:
272 raise RelaxError("The self.mf_models user variable '%s' is incorrectly set. It must be one of %s." % (self.mf_models, mf_models))
273 for i in range(len(self.local_tm_models)):
274 if self.local_tm_models[i] not in local_tm_models:
275 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))
276
277
278 if not exists_mol_res_spin_data():
279 raise RelaxNoSequenceError(self.pipe_name)
280
281
282 if not hasattr(cdp, 'ri_ids') or len(cdp.ri_ids) == 0:
283 raise RelaxNoRiError(ri_id)
284
285
286 if len(cdp.ri_ids) <= 3:
287 raise RelaxError("Insufficient relaxation data, 4 or more data sets are essential for the execution of this script.")
288
289
290 for spin, spin_id in spin_loop(return_id=True):
291
292 if not spin.select:
293 continue
294
295
296 if not hasattr(spin, 'isotope') or spin.isotope == None:
297 raise RelaxNoValueError("nuclear isotope type", spin_id=spin_id)
298
299
300 if not hasattr(spin, 'ri_data') or spin.ri_data == None:
301 continue
302
303
304 if not hasattr(spin, 'csa') or spin.csa == None:
305 raise RelaxNoValueError("CSA", spin_id=spin_id)
306
307
308 for interatom in interatomic_loop():
309
310 spin1 = return_spin(interatom.spin_id1)
311 spin2 = return_spin(interatom.spin_id2)
312
313
314 if not spin1.select or not spin2.select:
315 continue
316
317
318 if not hasattr(interatom, 'r') or interatom.r == None:
319 raise RelaxNoValueError("interatomic distance", spin_id=interatom.spin_id1, spin_id2=interatom.spin_id2)
320
321
322 if not isinstance(self.grid_inc, int):
323 raise RelaxError("The grid_inc user variable '%s' is incorrectly set. It should be an integer." % self.grid_inc)
324 if not isinstance(self.diff_tensor_grid_inc, dict):
325 raise RelaxError("The diff_tensor_grid_inc user variable '%s' is incorrectly set. It should be a dictionary." % self.diff_tensor_grid_inc)
326 for tensor in ['sphere', 'prolate', 'oblate', 'ellipsoid']:
327 if not tensor in self.diff_tensor_grid_inc:
328 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))
329 if not isinstance(self.diff_tensor_grid_inc[tensor], int):
330 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))
331 if not isinstance(self.min_algor, str):
332 raise RelaxError("The min_algor user variable '%s' is incorrectly set. It should be a string." % self.min_algor)
333 if not isinstance(self.mc_sim_num, int):
334 raise RelaxError("The mc_sim_num user variable '%s' is incorrectly set. It should be an integer." % self.mc_sim_num)
335
336
337 if not isinstance(self.conv_loop, bool):
338 raise RelaxError("The conv_loop user variable '%s' is incorrectly set. It should be one of the booleans True or False." % self.conv_loop)
339
340
342 """Test for the convergence of the global model."""
343
344
345 print("\n\n\n")
346 print("#####################")
347 print("# Convergence tests #")
348 print("#####################\n")
349
350
351 if self.max_iter and self.round > self.max_iter:
352 print("Maximum number of global iterations reached. Terminating the protocol before convergence has been reached.")
353 return True
354
355
356 self.conv_data.chi2.append(cdp.chi2)
357
358
359 curr_models = ''
360 for spin in spin_loop():
361 if hasattr(spin, 'model'):
362 if not spin.model == 'None':
363 curr_models = curr_models + spin.model
364 self.conv_data.models.append(curr_models)
365
366
367 self.conv_data.diff_vals.append([])
368 for param in self.conv_data.diff_params:
369
370 self.conv_data.diff_vals[-1].append(getattr(cdp.diff_tensor, param))
371
372
373 self.conv_data.mf_vals.append([])
374 self.conv_data.mf_params.append([])
375 self.conv_data.spin_ids.append([])
376 for spin, spin_id in spin_loop(return_id=True):
377
378 if not hasattr(spin, 'params'):
379 continue
380
381
382 self.conv_data.spin_ids[-1].append(spin_id)
383 self.conv_data.mf_params[-1].append([])
384 self.conv_data.mf_vals[-1].append([])
385
386
387 for j in range(len(spin.params)):
388
389 self.conv_data.mf_params[-1][-1].append(spin.params[j])
390 self.conv_data.mf_vals[-1][-1].append(getattr(spin, spin.params[j].lower()))
391
392
393 if self.round == 1:
394 print("First round of optimisation, skipping the convergence tests.\n\n\n")
395 return False
396
397
398 converged = False
399 for i in range(self.start_round, self.round - 1):
400
401 print("\n\n\n# Comparing the current iteration to iteration %i.\n" % (i+1))
402
403
404 index = i - self.start_round
405
406
407 print("Chi-squared test:")
408 print(" chi2 (iter %i): %s" % (i+1, self.conv_data.chi2[index]))
409 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.chi2[index]))
410 print(" chi2 (iter %i): %s" % (self.round, self.conv_data.chi2[-1]))
411 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.chi2[-1]))
412 print(" chi2 (difference): %s" % (self.conv_data.chi2[index] - self.conv_data.chi2[-1]))
413 if self.conv_data.chi2[index] == self.conv_data.chi2[-1]:
414 print(" The chi-squared value has converged.\n")
415 else:
416 print(" The chi-squared value has not converged.\n")
417 continue
418
419
420 print("Identical model-free models test:")
421 if self.conv_data.models[index] == self.conv_data.models[-1]:
422 print(" The model-free models have converged.\n")
423 else:
424 print(" The model-free models have not converged.\n")
425 continue
426
427
428 print("Identical diffusion tensor parameter test:")
429 params_converged = True
430 for k in range(len(self.conv_data.diff_params)):
431
432 if self.conv_data.diff_vals[index][k] != self.conv_data.diff_vals[-1][k]:
433 print(" Parameter: %s" % param)
434 print(" Value (iter %i): %s" % (i+1, self.conv_data.diff_vals[index][k]))
435 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.diff_vals[index][k]))
436 print(" Value (iter %i): %s" % (self.round, self.conv_data.diff_vals[-1][k]))
437 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.diff_vals[-1][k]))
438 print(" The diffusion parameters have not converged.\n")
439 params_converged = False
440 break
441 if not params_converged:
442 continue
443 print(" The diffusion tensor parameters have converged.\n")
444
445
446 print("\nIdentical model-free parameter test:")
447 if len(self.conv_data.spin_ids[index]) != len(self.conv_data.spin_ids[-1]):
448 print(" Different number of spins.")
449 continue
450 for j in range(len(self.conv_data.spin_ids[-1])):
451
452 for k in range(len(self.conv_data.mf_params[-1][j])):
453
454 if self.conv_data.mf_vals[index][j][k] != self.conv_data.mf_vals[-1][j][k]:
455 print(" Spin ID: %s" % self.conv_data.spin_ids[-1][j])
456 print(" Parameter: %s" % self.conv_data.mf_params[-1][j][k])
457 print(" Value (iter %i): %s" % (i+1, self.conv_data.mf_vals[index][j][k]))
458 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.mf_vals[index][j][k]))
459 print(" Value (iter %i): %s" % (self.round, self.conv_data.mf_vals[-1][j][k]))
460 print(" (as an IEEE-754 byte array: %s)" % floatAsByteArray(self.conv_data.mf_vals[index][j][k]))
461 print(" The model-free parameters have not converged.\n")
462 params_converged = False
463 break
464 if not params_converged:
465 continue
466 print(" The model-free parameters have converged.\n")
467
468
469 converged = True
470 break
471
472
473
474
475
476 print("\nConvergence:")
477 if converged:
478
479 status.auto_analysis[self.pipe_bundle].convergence = True
480
481
482 print(" [ Yes ]")
483
484
485 return True
486 else:
487
488 print(" [ No ]")
489
490
491 return False
492
493
495 """Function for returning the name of next round of optimisation."""
496
497
498 try:
499 dir_list = listdir(self.results_dir+sep+model)
500 except:
501 return 0
502
503
504 if 'init' not in dir_list:
505 return 0
506
507
508 rnd_dirs = []
509 for file in dir_list:
510 if search('^round_', file):
511 rnd_dirs.append(file)
512
513
514 numbers = []
515 for dir in rnd_dirs:
516 try:
517 numbers.append(int(dir[6:]))
518 except:
519 pass
520 numbers.sort()
521
522
523 if not len(numbers):
524 return 1
525
526
527 max_round = numbers[-1]
528
529
530 for i in range(max_round, -1, -1):
531
532 complete_round = i
533
534
535 file_root = self.results_dir + sep + model + sep + "round_%i" % i + sep + 'opt' + sep + 'results'
536
537
538 if access(file_root + '.bz2', F_OK):
539 break
540 if access(file_root + '.gz', F_OK):
541 break
542 if access(file_root, F_OK):
543 break
544
545
546 if complete_round == 0:
547 return 0
548
549
550 return complete_round + 1
551
552
554 """Execute the protocol."""
555
556
557
558
559 if self.diff_model == 'local_tm':
560
561 self.base_dir = self.results_dir+'local_tm'+sep
562
563
564 self.multi_model(local_tm=True)
565
566
567 self.model_selection(modsel_pipe=self.name_pipe('aic'), dir=self.base_dir + 'aic')
568
569
570
571
572
573 elif self.diff_model == 'sphere' or self.diff_model == 'prolate' or self.diff_model == 'oblate' or self.diff_model == 'ellipsoid':
574
575 dir_list = listdir(self.results_dir)
576 if 'local_tm' not in dir_list:
577 raise RelaxError("The local_tm model must be optimised first.")
578
579
580 self.start_round = self.determine_rnd(model=self.diff_model)
581
582
583
584 while True:
585
586 self.round = self.determine_rnd(model=self.diff_model)
587 status.auto_analysis[self.pipe_bundle].round = self.round
588
589
590 if self.round == 0:
591
592 self.base_dir = self.results_dir+self.diff_model+sep+'init'+sep
593
594
595 name = self.name_pipe(self.diff_model)
596
597
598 if has_pipe(name):
599 self.interpreter.pipe.delete(name)
600 self.interpreter.pipe.create(name, 'mf', bundle=self.pipe_bundle)
601
602
603 self.interpreter.results.read(file='results', dir=self.results_dir+'local_tm'+sep+'aic')
604
605
606 self.interpreter.model_free.remove_tm()
607
608
609 if self.diff_model == 'sphere':
610 self.interpreter.diffusion_tensor.init(10e-9, fixed=False)
611 inc = self.diff_tensor_grid_inc['sphere']
612 elif self.diff_model == 'prolate':
613 self.interpreter.diffusion_tensor.init((10e-9, 0, 0, 0), spheroid_type='prolate', fixed=False)
614 inc = self.diff_tensor_grid_inc['prolate']
615 elif self.diff_model == 'oblate':
616 self.interpreter.diffusion_tensor.init((10e-9, 0, 0, 0), spheroid_type='oblate', fixed=False)
617 inc = self.diff_tensor_grid_inc['oblate']
618 elif self.diff_model == 'ellipsoid':
619 self.interpreter.diffusion_tensor.init((10e-09, 0, 0, 0, 0, 0), fixed=False)
620 inc = self.diff_tensor_grid_inc['ellipsoid']
621
622
623 self.interpreter.fix('all_spins')
624 self.interpreter.grid_search(inc=inc)
625 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
626
627
628 self.interpreter.results.write(file='results', dir=self.base_dir, force=True)
629
630
631
632 else:
633
634 self.base_dir = self.results_dir+self.diff_model + sep+'round_'+repr(self.round)+sep
635
636
637 self.load_tensor()
638
639
640 self.multi_model()
641
642
643 self.model_selection(modsel_pipe=self.name_pipe('aic'), dir=self.base_dir + 'aic')
644
645
646 self.interpreter.fix('all', fixed=False)
647
648
649 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
650
651
652 dir = self.base_dir + 'opt'
653 self.interpreter.results.write(file='results', dir=dir, force=True)
654
655
656 converged = self.convergence()
657
658
659 if converged or not self.conv_loop:
660 break
661
662
663 status.auto_analysis[self.pipe_bundle].round = None
664
665
666
667
668
669 elif self.diff_model == 'final':
670
671
672
673
674 dir_list = listdir(self.results_dir)
675
676
677 min_models = ['local_tm', 'sphere']
678 for model in min_models:
679 if model not in dir_list:
680 raise RelaxError("The minimum set of global diffusion models required for the protocol have not been optimised, the '%s' model results cannot be found." % model)
681
682
683 all_models = ['local_tm', 'sphere', 'prolate', 'oblate', 'ellipsoid']
684 self.opt_models = []
685 self.pipes = []
686 for model in all_models:
687 if model in dir_list:
688 self.opt_models.append(model)
689 self.pipes.append(self.name_pipe(model))
690
691
692 for name in pipe_names(bundle=self.pipe_bundle):
693 if name in self.pipes + self.mf_model_pipes + self.local_tm_model_pipes + [self.name_pipe('aic'), self.name_pipe('previous')]:
694 self.interpreter.pipe.delete(name)
695
696
697 self.interpreter.pipe.create(self.name_pipe('local_tm'), 'mf', bundle=self.pipe_bundle)
698
699
700 self.interpreter.results.read(file='results', dir=self.results_dir+'local_tm'+sep+'aic')
701
702
703 for model in ['sphere', 'prolate', 'oblate', 'ellipsoid']:
704
705 if model not in self.opt_models:
706 continue
707
708
709 self.round = self.determine_rnd(model=model) - 1
710
711
712 if self.round < 1:
713
714 name = model
715 if model == 'prolate' or model == 'oblate':
716 name = name + ' spheroid'
717
718
719 raise RelaxError("Multiple rounds of optimisation of the " + name + " (between 8 to 15) are required for the proper execution of this script.")
720
721
722 self.interpreter.pipe.create(self.name_pipe(model), 'mf', bundle=self.pipe_bundle)
723
724
725 self.interpreter.results.read(file='results', dir=self.results_dir+model + sep+'round_'+repr(self.round)+sep+'opt')
726
727
728 self.model_selection(modsel_pipe=self.name_pipe('final'), write_flag=False)
729
730
731
732
733
734
735 if hasattr(get_pipe(self.name_pipe('final')), 'diff_tensor'):
736 self.interpreter.fix('diff')
737
738
739 self.interpreter.monte_carlo.setup(number=self.mc_sim_num)
740 self.interpreter.monte_carlo.create_data()
741 self.interpreter.monte_carlo.initial_values()
742 self.interpreter.minimise(self.min_algor, func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations)
743 self.interpreter.eliminate()
744 self.interpreter.monte_carlo.error_analysis()
745
746
747
748
749
750
751 self.write_results()
752
753
754
755
756
757 else:
758 raise RelaxError("Unknown diffusion model, change the value of 'self.diff_model'")
759
760
776
777
789
790
836
837
839 """Generate a unique name for the data pipe.
840
841 @param prefix: The prefix of the data pipe name.
842 @type prefix: str
843 """
844
845
846 name = "%s - %s" % (prefix, self.pipe_bundle)
847
848
849 return name
850
851
879
880
882 """Create Grace plots of the final model-free results."""
883
884
885 dir = self.write_results_dir + 'final'
886 self.interpreter.results.write(file='results', dir=dir, force=True)
887
888
889 dir = self.write_results_dir + 'final' + sep + 'grace'
890 self.interpreter.grace.write(x_data_type='res_num', y_data_type='s2', file='s2.agr', dir=dir, force=True)
891 self.interpreter.grace.write(x_data_type='res_num', y_data_type='s2f', file='s2f.agr', dir=dir, force=True)
892 self.interpreter.grace.write(x_data_type='res_num', y_data_type='s2s', file='s2s.agr', dir=dir, force=True)
893 self.interpreter.grace.write(x_data_type='res_num', y_data_type='te', file='te.agr', dir=dir, force=True)
894 self.interpreter.grace.write(x_data_type='res_num', y_data_type='tf', file='tf.agr', dir=dir, force=True)
895 self.interpreter.grace.write(x_data_type='res_num', y_data_type='ts', file='ts.agr', dir=dir, force=True)
896 self.interpreter.grace.write(x_data_type='res_num', y_data_type='rex', file='rex.agr', dir=dir, force=True)
897 self.interpreter.grace.write(x_data_type='s2', y_data_type='te', file='s2_vs_te.agr', dir=dir, force=True)
898 self.interpreter.grace.write(x_data_type='s2', y_data_type='rex', file='s2_vs_rex.agr', dir=dir, force=True)
899 self.interpreter.grace.write(x_data_type='te', y_data_type='rex', file='te_vs_rex.agr', dir=dir, force=True)
900
901
902 dir = self.write_results_dir + 'final'
903 self.interpreter.value.write(param='s2', file='s2.txt', dir=dir, force=True)
904 self.interpreter.value.write(param='s2f', file='s2f.txt', dir=dir, force=True)
905 self.interpreter.value.write(param='s2s', file='s2s.txt', dir=dir, force=True)
906 self.interpreter.value.write(param='te', file='te.txt', dir=dir, force=True)
907 self.interpreter.value.write(param='tf', file='tf.txt', dir=dir, force=True)
908 self.interpreter.value.write(param='ts', file='ts.txt', dir=dir, force=True)
909 self.interpreter.value.write(param='rex', file='rex.txt', dir=dir, force=True)
910 self.interpreter.value.write(param='local_tm', file='local_tm.txt', dir=dir, force=True)
911 frqs = spectrometer.get_frequencies()
912 for i in range(len(frqs)):
913 comment = "This is the Rex value with units rad.s^-1 scaled to a magnetic field strength of %s MHz." % (frqs[i]/1e6)
914 self.interpreter.value.write(param='rex', file='rex_%s.txt'%int(frqs[i]/1e6), dir=dir, scaling=(2.0*pi*frqs[i])**2, comment=comment, force=True)
915
916
917 dir = self.write_results_dir + 'final' + sep + 'pymol'
918 self.interpreter.pymol.macro_write(data_type='s2', dir=dir, force=True)
919 self.interpreter.pymol.macro_write(data_type='s2f', dir=dir, force=True)
920 self.interpreter.pymol.macro_write(data_type='s2s', dir=dir, force=True)
921 self.interpreter.pymol.macro_write(data_type='amp_fast', dir=dir, force=True)
922 self.interpreter.pymol.macro_write(data_type='amp_slow', dir=dir, force=True)
923 self.interpreter.pymol.macro_write(data_type='te', dir=dir, force=True)
924 self.interpreter.pymol.macro_write(data_type='tf', dir=dir, force=True)
925 self.interpreter.pymol.macro_write(data_type='ts', dir=dir, force=True)
926 self.interpreter.pymol.macro_write(data_type='time_fast', dir=dir, force=True)
927 self.interpreter.pymol.macro_write(data_type='time_slow', dir=dir, force=True)
928 self.interpreter.pymol.macro_write(data_type='rex', dir=dir, force=True)
929
930
931 dir = self.write_results_dir + 'final' + sep + 'molmol'
932 self.interpreter.molmol.macro_write(data_type='s2', dir=dir, force=True)
933 self.interpreter.molmol.macro_write(data_type='s2f', dir=dir, force=True)
934 self.interpreter.molmol.macro_write(data_type='s2s', dir=dir, force=True)
935 self.interpreter.molmol.macro_write(data_type='amp_fast', dir=dir, force=True)
936 self.interpreter.molmol.macro_write(data_type='amp_slow', dir=dir, force=True)
937 self.interpreter.molmol.macro_write(data_type='te', dir=dir, force=True)
938 self.interpreter.molmol.macro_write(data_type='tf', dir=dir, force=True)
939 self.interpreter.molmol.macro_write(data_type='ts', dir=dir, force=True)
940 self.interpreter.molmol.macro_write(data_type='time_fast', dir=dir, force=True)
941 self.interpreter.molmol.macro_write(data_type='time_slow', dir=dir, force=True)
942 self.interpreter.molmol.macro_write(data_type='rex', dir=dir, force=True)
943
944
945 if hasattr(cdp, 'structure') and hasattr(cdp, 'diff_tensor'):
946 dir = self.write_results_dir + 'final'
947 self.interpreter.structure.create_diff_tensor_pdb(file="tensor.pdb", dir=dir, force=True)
948
949
950
952 """Empty container for data storage."""
953