1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 from copy import deepcopy
25 from math import pi
26 from minfx.grid import grid_split
27 from numpy import array, dot, float64, int8, zeros
28 from numpy.linalg import inv
29 from re import match, search
30 import sys
31 from warnings import warn
32
33
34 import arg_check
35 from float import isNaN, isInf
36 from generic_fns import diffusion_tensor, pipes
37 from generic_fns.diffusion_tensor import diff_data_exists
38 from generic_fns.mol_res_spin import count_spins, exists_mol_res_spin_data, return_spin_from_index, spin_loop
39 from maths_fns.mf import Mf
40 from multi import Processor_box
41 from multi_processor_commands import MF_grid_command, MF_memo, MF_minimise_command
42 from physical_constants import h_bar, mu0, return_gyromagnetic_ratio
43 from relax_errors import RelaxError, RelaxInfError, RelaxLenError, RelaxMultiVectorError, RelaxNaNError, RelaxNoModelError, RelaxNoPdbError, RelaxNoResError, RelaxNoSequenceError, RelaxNoTensorError, RelaxNoValueError, RelaxNoVectorsError, RelaxNucleusError, RelaxProtonTypeError, RelaxSpinTypeError
44 from relax_warnings import RelaxWarning
45
46
47
49 """Empty class to be used for data storage."""
50
51
53 """Class containing functions specific to model-free optimisation."""
54
56 """Disassemble the model-free parameter vector.
57
58 @param model_type: The model-free model type. This must be one of 'mf', 'local_tm',
59 'diff', or 'all'.
60 @type model_type: str
61 @keyword param_vector: The model-free parameter vector.
62 @type param_vector: numpy array
63 @keyword spin: The spin data container. If this argument is supplied, then the spin_id
64 argument will be ignored.
65 @type spin: SpinContainer instance
66 @keyword spin_id: The spin identification string.
67 @type spin_id: str
68 @keyword sim_index: The optional MC simulation index.
69 @type sim_index: int
70 """
71
72
73 param_index = 0
74
75
76 if sim_index != None and (model_type == 'diff' or model_type == 'all'):
77
78 if cdp.diff_tensor.type == 'sphere':
79
80 cdp.diff_tensor.tm_sim[sim_index] = param_vector[0]
81
82
83 param_index = param_index + 1
84
85
86 elif cdp.diff_tensor.type == 'spheroid':
87
88 cdp.diff_tensor.tm_sim[sim_index] = param_vector[0]
89 cdp.diff_tensor.Da_sim[sim_index] = param_vector[1]
90 cdp.diff_tensor.theta_sim[sim_index] = param_vector[2]
91 cdp.diff_tensor.phi_sim[sim_index] = param_vector[3]
92 diffusion_tensor.fold_angles(sim_index=sim_index)
93
94
95 param_index = param_index + 4
96
97
98 elif cdp.diff_tensor.type == 'ellipsoid':
99
100 cdp.diff_tensor.tm_sim[sim_index] = param_vector[0]
101 cdp.diff_tensor.Da_sim[sim_index] = param_vector[1]
102 cdp.diff_tensor.Dr_sim[sim_index] = param_vector[2]
103 cdp.diff_tensor.alpha_sim[sim_index] = param_vector[3]
104 cdp.diff_tensor.beta_sim[sim_index] = param_vector[4]
105 cdp.diff_tensor.gamma_sim[sim_index] = param_vector[5]
106 diffusion_tensor.fold_angles(sim_index=sim_index)
107
108
109 param_index = param_index + 6
110
111
112 elif model_type == 'diff' or model_type == 'all':
113
114 if cdp.diff_tensor.type == 'sphere':
115
116 cdp.diff_tensor.tm = param_vector[0]
117
118
119 param_index = param_index + 1
120
121
122 elif cdp.diff_tensor.type == 'spheroid':
123
124 cdp.diff_tensor.tm = param_vector[0]
125 cdp.diff_tensor.Da = param_vector[1]
126 cdp.diff_tensor.theta = param_vector[2]
127 cdp.diff_tensor.phi = param_vector[3]
128 diffusion_tensor.fold_angles()
129
130
131 param_index = param_index + 4
132
133
134 elif cdp.diff_tensor.type == 'ellipsoid':
135
136 cdp.diff_tensor.tm = param_vector[0]
137 cdp.diff_tensor.Da = param_vector[1]
138 cdp.diff_tensor.Dr = param_vector[2]
139 cdp.diff_tensor.alpha = param_vector[3]
140 cdp.diff_tensor.beta = param_vector[4]
141 cdp.diff_tensor.gamma = param_vector[5]
142 diffusion_tensor.fold_angles()
143
144
145 param_index = param_index + 6
146
147
148 if model_type != 'diff':
149
150 if spin:
151 loop = [spin]
152 else:
153 loop = spin_loop(spin_id)
154
155
156 for spin in loop:
157
158 if not spin.select:
159 continue
160
161
162 for j in xrange(len(spin.params)):
163
164 if spin.params[j] == 'local_tm':
165 if sim_index == None:
166 spin.local_tm = param_vector[param_index]
167 else:
168 spin.local_tm_sim[sim_index] = param_vector[param_index]
169
170
171 elif spin.params[j] == 's2':
172 if sim_index == None:
173 spin.s2 = param_vector[param_index]
174 else:
175 spin.s2_sim[sim_index] = param_vector[param_index]
176
177
178 elif spin.params[j] == 's2f':
179 if sim_index == None:
180 spin.s2f = param_vector[param_index]
181 else:
182 spin.s2f_sim[sim_index] = param_vector[param_index]
183
184
185 elif spin.params[j] == 's2s':
186 if sim_index == None:
187 spin.s2s = param_vector[param_index]
188 else:
189 spin.s2s_sim[sim_index] = param_vector[param_index]
190
191
192 elif spin.params[j] == 'te':
193 if sim_index == None:
194 spin.te = param_vector[param_index]
195 else:
196 spin.te_sim[sim_index] = param_vector[param_index]
197
198
199 elif spin.params[j] == 'tf':
200 if sim_index == None:
201 spin.tf = param_vector[param_index]
202 else:
203 spin.tf_sim[sim_index] = param_vector[param_index]
204
205
206 elif spin.params[j] == 'ts':
207 if sim_index == None:
208 spin.ts = param_vector[param_index]
209 else:
210 spin.ts_sim[sim_index] = param_vector[param_index]
211
212
213 elif spin.params[j] == 'rex':
214 if sim_index == None:
215 spin.rex = param_vector[param_index]
216 else:
217 spin.rex_sim[sim_index] = param_vector[param_index]
218
219
220 elif spin.params[j] == 'r':
221 if sim_index == None:
222 spin.r = param_vector[param_index]
223 else:
224 spin.r_sim[sim_index] = param_vector[param_index]
225
226
227 elif spin.params[j] == 'csa':
228 if sim_index == None:
229 spin.csa = param_vector[param_index]
230 else:
231 spin.csa_sim[sim_index] = param_vector[param_index]
232
233
234 else:
235 raise RelaxError("Unknown parameter.")
236
237
238 param_index = param_index + 1
239
240
241 if model_type != 'diff':
242
243 if spin:
244 loop = [spin]
245 else:
246 loop = spin_loop(spin_id)
247
248
249 for spin in loop:
250
251 if not spin.select:
252 continue
253
254
255 if sim_index == None:
256
257 if 's2' not in spin.params and 's2f' in spin.params and 's2s' in spin.params:
258 spin.s2 = spin.s2f * spin.s2s
259
260
261 if 's2f' not in spin.params and 's2' in spin.params and 's2s' in spin.params:
262 if spin.s2s == 0.0:
263 spin.s2f = 1e99
264 else:
265 spin.s2f = spin.s2 / spin.s2s
266
267
268 if 's2s' not in spin.params and 's2' in spin.params and 's2f' in spin.params:
269 if spin.s2f == 0.0:
270 spin.s2s = 1e99
271 else:
272 spin.s2s = spin.s2 / spin.s2f
273
274
275 else:
276
277 if 's2' not in spin.params and 's2f' in spin.params and 's2s' in spin.params:
278 spin.s2_sim[sim_index] = spin.s2f_sim[sim_index] * spin.s2s_sim[sim_index]
279
280
281 if 's2f' not in spin.params and 's2' in spin.params and 's2s' in spin.params:
282 if spin.s2s_sim[sim_index] == 0.0:
283 spin.s2f_sim[sim_index] = 1e99
284 else:
285 spin.s2f_sim[sim_index] = spin.s2_sim[sim_index] / spin.s2s_sim[sim_index]
286
287
288 if 's2s' not in spin.params and 's2' in spin.params and 's2f' in spin.params:
289 if spin.s2f_sim[sim_index] == 0.0:
290 spin.s2s_sim[sim_index] = 1e99
291 else:
292 spin.s2s_sim[sim_index] = spin.s2_sim[sim_index] / spin.s2f_sim[sim_index]
293
294
295 - def _disassemble_result(self, param_vector=None, func=None, iter=None, fc=None, gc=None, hc=None, warning=None, spin=None, sim_index=None, model_type=None, scaling=None, scaling_matrix=None):
296 """Disassemble the optimisation results.
297
298 @keyword param_vector: The model-free parameter vector.
299 @type param_vector: numpy array
300 @keyword func: The optimised chi-squared value.
301 @type func: float
302 @keyword iter: The number of optimisation steps required to find the minimum.
303 @type iter: int
304 @keyword fc: The function count.
305 @type fc: int
306 @keyword gc: The gradient count.
307 @type gc: int
308 @keyword hc: The Hessian count.
309 @type hc: int
310 @keyword warning: Any optimisation warnings.
311 @type warning: str or None
312 @keyword spin: The spin container.
313 @type spin: SpinContainer instance or None
314 @keyword sim_index: The Monte Carlo simulation index.
315 @type sim_index: int or None
316 @keyword model_type: The model-free model type, one of 'mf', 'local_tm', 'diff', or
317 'all'.
318 @type model_type: str
319 @keyword scaling: If True, diagonal scaling is enabled during optimisation to
320 allow the problem to be better conditioned.
321 @type scaling: bool
322 @keyword scaling_matrix: The diagonal, square scaling matrix.
323 @type scaling_matrix: numpy diagonal matrix
324 """
325
326
327 cdp = pipes.get_pipe()
328
329
330 if isInf(func):
331 raise RelaxInfError('chi-squared')
332
333
334 if isNaN(func):
335 raise RelaxNaNError('chi-squared')
336
337
338 if scaling:
339 param_vector = dot(scaling_matrix, param_vector)
340
341
342 if sim_index == None:
343
344 chi2 = None
345 if (model_type == 'mf' or model_type == 'local_tm') and hasattr(cdp, 'chi2'):
346 chi2 = spin.chi2
347 if (model_type == 'diff' or model_type == 'all') and hasattr(cdp, 'chi2'):
348 chi2 = cdp.chi2
349
350
351 if chi2 != None and func >= chi2:
352 print("Discarding the optimisation results, the optimised chi-squared value is higher than the current value (%s >= %s)." % (func, chi2))
353
354
355 return
356
357
358 else:
359 print("Storing the optimisation results, the optimised chi-squared value is lower than the current value (%s < %s)." % (func, chi2))
360
361
362 self._disassemble_param_vector(model_type, param_vector=param_vector, spin=spin, sim_index=sim_index)
363
364
365 if sim_index != None:
366
367 if model_type == 'mf' or model_type == 'local_tm':
368
369
370 spin.chi2_sim[sim_index] = func
371
372
373 spin.iter_sim[sim_index] = iter
374
375
376 spin.f_count_sim[sim_index] = fc
377
378
379 spin.g_count_sim[sim_index] = gc
380
381
382 spin.h_count_sim[sim_index] = hc
383
384
385 spin.warning_sim[sim_index] = warning
386
387
388 elif model_type == 'diff' or model_type == 'all':
389
390 cdp.chi2_sim[sim_index] = func
391
392
393 cdp.iter_sim[sim_index] = iter
394
395
396 cdp.f_count_sim[sim_index] = fc
397
398
399 cdp.g_count_sim[sim_index] = gc
400
401
402 cdp.h_count_sim[sim_index] = hc
403
404
405 cdp.warning_sim[sim_index] = warning
406
407
408 else:
409
410 if model_type == 'mf' or model_type == 'local_tm':
411
412 spin.chi2 = func
413
414
415 spin.iter = iter
416
417
418 spin.f_count = fc
419
420
421 spin.g_count = gc
422
423
424 spin.h_count = hc
425
426
427 spin.warning = warning
428
429
430 elif model_type == 'diff' or model_type == 'all':
431
432 cdp.chi2 = func
433
434
435 cdp.iter = iter
436
437
438 cdp.f_count = fc
439
440
441 cdp.g_count = gc
442
443
444 cdp.h_count = hc
445
446
447 cdp.warning = warning
448
449
450 - def _grid_search_config(self, num_params, spin=None, spin_id=None, lower=None, upper=None, inc=None, scaling_matrix=None, verbosity=1):
451 """Configure the grid search.
452
453 @param num_params: The number of parameters in the model.
454 @type num_params: int
455 @keyword spin: The spin data container.
456 @type spin: SpinContainer instance
457 @keyword spin_id: The spin identification string.
458 @type spin_id: str
459 @keyword lower: The lower bounds of the grid search which must be equal to the
460 number of parameters in the model.
461 @type lower: array of numbers
462 @keyword upper: The upper bounds of the grid search which must be equal to the
463 number of parameters in the model.
464 @type upper: array of numbers
465 @keyword inc: The increments for each dimension of the space for the grid
466 search. The number of elements in the array must equal to the
467 number of parameters in the model.
468 @type inc: array of int
469 @keyword scaling_matrix: The diagonal, square scaling matrix.
470 @type scaling_matrix: numpy diagonal matrix
471 @keyword verbosity: A flag specifying the amount of information to print. The
472 higher the value, the greater the verbosity.
473 @type verbosity: int
474 """
475
476
477 self.test_grid_ops(lower=lower, upper=upper, inc=inc, n=num_params)
478
479
480 if isinstance(inc, int):
481 inc = [inc]*num_params
482
483
484 if not lower:
485
486 lower = []
487 upper = []
488
489
490 model_type = self._determine_model_type()
491
492
493 if model_type == 'diff' or model_type == 'all':
494
495 self._grid_search_diff_bounds(lower, upper)
496
497
498 if model_type != 'diff':
499
500 if spin:
501 loop = [spin]
502 else:
503 loop = spin_loop(spin_id)
504
505
506 for spin in loop:
507
508 if not spin.select:
509 continue
510
511
512 self._grid_search_spin_bounds(spin, lower, upper)
513
514
515 lower_new = []
516 upper_new = []
517 for i in xrange(num_params):
518 lower_new.append(lower[i] / scaling_matrix[i, i])
519 upper_new.append(upper[i] / scaling_matrix[i, i])
520
521
522 return inc, lower_new, upper_new
523
524
526 """Set up the default grid search bounds the diffusion tensor.
527
528 This method appends the default bounds to the lower and upper lists.
529
530 @param lower: The lower bound list to append to.
531 @type lower: list
532 @param upper: The upper bound list to append to.
533 @type upper: list
534 """
535
536
537 if cdp.diff_tensor.type == 'sphere':
538 lower.append(1.0 * 1e-9)
539 upper.append(12.0 * 1e-9)
540
541
542 if cdp.diff_tensor.type == 'spheroid':
543
544 lower.append(1.0 * 1e-9)
545 upper.append(12.0 * 1e-9)
546
547
548 if cdp.diff_tensor.spheroid_type == 'prolate':
549 lower.append(0.0)
550 upper.append(1e7)
551 elif cdp.diff_tensor.spheroid_type == 'oblate':
552 lower.append(-1e7)
553 upper.append(0.0)
554 else:
555 lower.append(-1e7)
556 upper.append(1e7)
557
558
559 lower.append(0.0)
560 upper.append(pi)
561
562
563 lower.append(0.0)
564 upper.append(pi)
565
566
567 elif cdp.diff_tensor.type == 'ellipsoid':
568
569 lower.append(1.0 * 1e-9)
570 upper.append(12.0 * 1e-9)
571
572
573 lower.append(0.0)
574 upper.append(1e7)
575
576
577 lower.append(0.0)
578 upper.append(1.0)
579
580
581 lower.append(0.0)
582 upper.append(pi)
583
584
585 lower.append(0.0)
586 upper.append(pi)
587
588
589 lower.append(0.0)
590 upper.append(pi)
591
592
594 """Set up the default grid search bounds for a single spin.
595
596 This method appends the default bounds to the lower and upper lists. The ordering of the
597 lists in min_options matches that of the params list in the spin container.
598
599 @param spin: A SpinContainer object.
600 @type spin: class instance
601 @param lower: The lower bound list to append to.
602 @type lower: list
603 @param upper: The upper bound list to append to.
604 @type upper: list
605 """
606
607
608 for i in xrange(len(spin.params)):
609
610 if spin.params[i] == 'local_tm':
611 lower.append(1.0 * 1e-9)
612 upper.append(12.0 * 1e-9)
613
614
615 elif match('s2', spin.params[i]):
616 lower.append(0.0)
617 upper.append(1.0)
618
619
620 elif match('t', spin.params[i]):
621 lower.append(0.0)
622 upper.append(500.0 * 1e-12)
623
624
625 elif spin.params[i] == 'rex':
626 lower.append(0.0)
627 upper.append(5.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2)
628
629
630 elif spin.params[i] == 'r':
631 lower.append(1.0 * 1e-10)
632 upper.append(1.05 * 1e-10)
633
634
635 elif spin.params[i] == 'csa':
636 lower.append(-120 * 1e-6)
637 upper.append(-200 * 1e-6)
638
639
640 else:
641 raise RelaxError("Unknown model-free parameter.")
642
643
644 - def _linear_constraints(self, num_params, model_type=None, spin=None, spin_id=None, scaling_matrix=None):
645 """Set up the model-free linear constraint matrices A and b.
646
647 Standard notation
648 =================
649
650 The order parameter constraints are::
651
652 0 <= S2 <= 1
653 0 <= S2f <= 1
654 0 <= S2s <= 1
655
656 By substituting the formula S2 = S2f.S2s into the above inequalities, the additional two
657 inequalities can be derived::
658
659 S2 <= S2f
660 S2 <= S2s
661
662 Correlation time constraints are::
663
664 te >= 0
665 tf >= 0
666 ts >= 0
667
668 tf <= ts
669
670 te, tf, ts <= 2 * tm
671
672 Additional constraints used include::
673
674 Rex >= 0
675 0.9e-10 <= r <= 2e-10
676 -300e-6 <= CSA <= 0
677
678
679 Rearranged notation
680 ===================
681
682 The above inequality constraints can be rearranged into::
683
684 S2 >= 0
685 -S2 >= -1
686 S2f >= 0
687 -S2f >= -1
688 S2s >= 0
689 -S2s >= -1
690 S2f - S2 >= 0
691 S2s - S2 >= 0
692 te >= 0
693 tf >= 0
694 ts >= 0
695 ts - tf >= 0
696 Rex >= 0
697 r >= 0.9e-10
698 -r >= -2e-10
699 CSA >= -300e-6
700 -CSA >= 0
701
702
703 Matrix notation
704 ===============
705
706 In the notation A.x >= b, where A is an matrix of coefficients, x is an array of parameter
707 values, and b is a vector of scalars, these inequality constraints are::
708
709 | 1 0 0 0 0 0 0 0 0 | | 0 |
710 | | | |
711 |-1 0 0 0 0 0 0 0 0 | | -1 |
712 | | | |
713 | 0 1 0 0 0 0 0 0 0 | | 0 |
714 | | | |
715 | 0 -1 0 0 0 0 0 0 0 | | -1 |
716 | | | |
717 | 0 0 1 0 0 0 0 0 0 | | S2 | | 0 |
718 | | | | | |
719 | 0 0 -1 0 0 0 0 0 0 | | S2f | | -1 |
720 | | | | | |
721 |-1 1 0 0 0 0 0 0 0 | | S2s | | 0 |
722 | | | | | |
723 |-1 0 1 0 0 0 0 0 0 | | te | | 0 |
724 | | | | | |
725 | 0 0 0 1 0 0 0 0 0 | . | tf | >= | 0 |
726 | | | | | |
727 | 0 0 0 0 1 0 0 0 0 | | ts | | 0 |
728 | | | | | |
729 | 0 0 0 0 0 1 0 0 0 | | Rex | | 0 |
730 | | | | | |
731 | 0 0 0 0 -1 1 0 0 0 | | r | | 0 |
732 | | | | | |
733 | 0 0 0 0 0 0 1 0 0 | | CSA | | 0 |
734 | | | |
735 | 0 0 0 0 0 0 0 1 0 | | 0.9e-10 |
736 | | | |
737 | 0 0 0 0 0 0 0 -1 0 | | -2e-10 |
738 | | | |
739 | 0 0 0 0 0 0 0 0 1 | | -300e-6 |
740 | | | |
741 | 0 0 0 0 0 0 0 0 -1 | | 0 |
742
743
744 @param num_params: The number of parameters in the model.
745 @type num_params: int
746 @keyword model_type: The model type, one of 'all', 'diff', 'mf', or 'local_tm'.
747 @type model_type: str
748 @keyword spin: The spin data container. If this argument is supplied, then the
749 spin_id argument will be ignored.
750 @type spin: SpinContainer instance
751 @keyword spin_id: The spin identification string.
752 @type spin_id: str
753 @keyword scaling_matrix: The diagonal, square scaling matrix.
754 @type scaling_matrix: numpy diagonal matrix
755 """
756
757
758 upper_time_limit = 1
759
760
761 A = []
762 b = []
763 zero_array = zeros(num_params, float64)
764 i = 0
765 j = 0
766
767
768 if model_type != 'mf' and diffusion_tensor.diff_data_exists():
769
770 if cdp.diff_tensor.type == 'sphere':
771
772 A.append(zero_array * 0.0)
773 A.append(zero_array * 0.0)
774 A[j][i] = 1.0
775 A[j+1][i] = -1.0
776 b.append(0.0 / scaling_matrix[i, i])
777 b.append(-200.0 * 1e-9 / scaling_matrix[i, i])
778 i = i + 1
779 j = j + 2
780
781
782 elif cdp.diff_tensor.type == 'spheroid':
783
784 A.append(zero_array * 0.0)
785 A.append(zero_array * 0.0)
786 A[j][i] = 1.0
787 A[j+1][i] = -1.0
788 b.append(0.0 / scaling_matrix[i, i])
789 b.append(-200.0 * 1e-9 / scaling_matrix[i, i])
790 i = i + 1
791 j = j + 2
792
793
794 if cdp.diff_tensor.spheroid_type == 'prolate':
795 A.append(zero_array * 0.0)
796 A[j][i] = 1.0
797 b.append(0.0 / scaling_matrix[i, i])
798 i = i + 1
799 j = j + 1
800
801
802 i = i + 2
803
804
805 elif cdp.diff_tensor.spheroid_type == 'oblate':
806 A.append(zero_array * 0.0)
807 A[j][i] = -1.0
808 b.append(0.0 / scaling_matrix[i, i])
809 i = i + 1
810 j = j + 1
811
812
813 i = i + 2
814
815 else:
816
817 i = i + 3
818
819
820 elif cdp.diff_tensor.type == 'ellipsoid':
821
822 A.append(zero_array * 0.0)
823 A.append(zero_array * 0.0)
824 A[j][i] = 1.0
825 A[j+1][i] = -1.0
826 b.append(0.0 / scaling_matrix[i, i])
827 b.append(-200.0 * 1e-9 / scaling_matrix[i, i])
828 i = i + 1
829 j = j + 2
830
831
832 A.append(zero_array * 0.0)
833 A[j][i] = 1.0
834 b.append(0.0 / scaling_matrix[i, i])
835 i = i + 1
836 j = j + 1
837
838
839 A.append(zero_array * 0.0)
840 A.append(zero_array * 0.0)
841 A[j][i] = 1.0
842 A[j+1][i] = -1.0
843 b.append(0.0 / scaling_matrix[i, i])
844 b.append(-1.0 / scaling_matrix[i, i])
845 i = i + 1
846 j = j + 2
847
848
849 i = i + 3
850
851
852 if model_type != 'diff':
853
854 if spin:
855 loop = [spin]
856 else:
857 loop = spin_loop(spin_id)
858
859
860 for spin in loop:
861
862 if not spin.select:
863 continue
864
865
866 old_i = i
867
868
869 for l in xrange(len(spin.params)):
870
871 if spin.params[l] == 'local_tm':
872 if upper_time_limit:
873
874 A.append(zero_array * 0.0)
875 A.append(zero_array * 0.0)
876 A[j][i] = 1.0
877 A[j+1][i] = -1.0
878 b.append(0.0 / scaling_matrix[i, i])
879 b.append(-200.0 * 1e-9 / scaling_matrix[i, i])
880 j = j + 2
881 else:
882
883 A.append(zero_array * 0.0)
884 A[j][i] = 1.0
885 b.append(0.0 / scaling_matrix[i, i])
886 j = j + 1
887
888
889 elif match('s2', spin.params[l]):
890
891 A.append(zero_array * 0.0)
892 A.append(zero_array * 0.0)
893 A[j][i] = 1.0
894 A[j+1][i] = -1.0
895 b.append(0.0 / scaling_matrix[i, i])
896 b.append(-1.0 / scaling_matrix[i, i])
897 j = j + 2
898
899
900 if spin.params[l] == 's2':
901 for m in xrange(len(spin.params)):
902 if spin.params[m] == 's2f' or spin.params[m] == 's2s':
903 A.append(zero_array * 0.0)
904 A[j][i] = -1.0
905 A[j][old_i+m] = 1.0
906 b.append(0.0)
907 j = j + 1
908
909
910 elif match('t[efs]', spin.params[l]):
911
912 A.append(zero_array * 0.0)
913 A[j][i] = 1.0
914 b.append(0.0 / scaling_matrix[i, i])
915 j = j + 1
916
917
918 if spin.params[l] == 'ts':
919 for m in xrange(len(spin.params)):
920 if spin.params[m] == 'tf':
921 A.append(zero_array * 0.0)
922 A[j][i] = 1.0
923 A[j][old_i+m] = -1.0
924 b.append(0.0)
925 j = j + 1
926
927
928 if upper_time_limit:
929 if not spin.params[l] == 'tf':
930 if model_type == 'mf':
931 A.append(zero_array * 0.0)
932 A[j][i] = -1.0
933 b.append(-2.0 * cdp.diff_tensor.tm / scaling_matrix[i, i])
934 else:
935 A.append(zero_array * 0.0)
936 A[j][0] = 2.0
937 A[j][i] = -1.0
938 b.append(0.0)
939
940 j = j + 1
941
942
943 elif spin.params[l] == 'rex':
944 A.append(zero_array * 0.0)
945 A[j][i] = 1.0
946 b.append(0.0 / scaling_matrix[i, i])
947 j = j + 1
948
949
950 elif spin.params[l] == 'r':
951
952 A.append(zero_array * 0.0)
953 A.append(zero_array * 0.0)
954 A[j][i] = 1.0
955 A[j+1][i] = -1.0
956 b.append(0.9e-10 / scaling_matrix[i, i])
957 b.append(-2e-10 / scaling_matrix[i, i])
958 j = j + 2
959
960
961 elif spin.params[l] == 'csa':
962
963 A.append(zero_array * 0.0)
964 A.append(zero_array * 0.0)
965 A[j][i] = 1.0
966 A[j+1][i] = -1.0
967 b.append(-300e-6 / scaling_matrix[i, i])
968 b.append(0.0 / scaling_matrix[i, i])
969 j = j + 2
970
971
972 i = i + 1
973
974
975 A = array(A, int8)
976 b = array(b, float64)
977
978 return A, b
979
980
981 - def _minimise_data_setup(self, data_store, min_algor, num_data_sets, min_options, spin=None, sim_index=None):
982 """Set up all the data required for minimisation.
983
984 @param data_store: A data storage container.
985 @type data_store: class instance
986 @param min_algor: The minimisation algorithm to use.
987 @type min_algor: str
988 @param num_data_sets: The number of data sets.
989 @type num_data_sets: int
990 @param min_options: The minimisation options array.
991 @type min_options: list
992 @keyword spin: The spin data container.
993 @type spin: SpinContainer instance
994 @keyword sim_index: The optional MC simulation index.
995 @type sim_index: int
996 @return: An insane tuple. The full tuple is (ri_data, ri_data_err, equations, param_types, param_values, r, csa, num_frq, frq, num_ri, remap_table, noe_r1_table, ri_types, num_params, xh_unit_vectors, diff_type, diff_params)
997 @rtype: tuple
998 """
999
1000
1001 data_store.ri_data = []
1002 data_store.ri_data_err = []
1003 data_store.equations = []
1004 data_store.param_types = []
1005 data_store.param_values = None
1006 data_store.r = []
1007 data_store.csa = []
1008 data_store.num_frq = []
1009 data_store.frq = []
1010 data_store.num_ri = []
1011 data_store.remap_table = []
1012 data_store.noe_r1_table = []
1013 data_store.ri_types = []
1014 data_store.gx = []
1015 data_store.gh = []
1016 data_store.num_params = []
1017 data_store.xh_unit_vectors = []
1018 if data_store.model_type == 'local_tm':
1019 data_store.mf_params = []
1020 elif data_store.model_type == 'diff':
1021 data_store.param_values = []
1022
1023
1024 if min_algor == 'back_calc':
1025
1026 data_store.ri_data = [0.0]
1027 data_store.ri_data_err = [0.000001]
1028 data_store.equations = [spin.equation]
1029 data_store.param_types = [spin.params]
1030 data_store.r = [spin.r]
1031 data_store.csa = [spin.csa]
1032 data_store.num_frq = [1]
1033 data_store.frq = [[min_options[3]]]
1034 data_store.num_ri = [1]
1035 data_store.remap_table = [[0]]
1036 data_store.noe_r1_table = [[None]]
1037 data_store.ri_types = [[min_options[2]]]
1038 data_store.gx = [return_gyromagnetic_ratio(spin.heteronuc_type)]
1039 data_store.gh = [return_gyromagnetic_ratio(spin.proton_type)]
1040 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
1041 data_store.xh_unit_vectors = [spin.xh_vect]
1042 else:
1043 data_store.xh_unit_vectors = [None]
1044
1045
1046 data_store.num_params = [len(spin.params)]
1047
1048
1049 for j in xrange(num_data_sets):
1050
1051 if data_store.model_type == 'diff' or data_store.model_type == 'all':
1052 spin_index = j
1053 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
1054
1055
1056 if not spin.select:
1057 continue
1058
1059
1060 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
1061 continue
1062
1063
1064 for ri_id in cdp.ri_ids:
1065
1066 err = spin.ri_data_err[ri_id]
1067
1068
1069 if err != None and err == 0.0:
1070 raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (errid))
1071 elif err != None and err < 0.0:
1072 raise RelaxError("Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (err, data_store.spin_id, ri_id))
1073
1074
1075 data = self._relax_data_opt_structs(spin, sim_index=sim_index)
1076
1077
1078 data_store.ri_data.append(data[0])
1079 data_store.ri_data_err.append(data[1])
1080 data_store.num_frq.append(data[2])
1081 data_store.num_ri.append(data[3])
1082 data_store.ri_types.append(data[4])
1083 data_store.frq.append(data[5])
1084 data_store.remap_table.append(data[6])
1085 data_store.noe_r1_table.append(data[7])
1086
1087
1088 data_store.equations.append(spin.equation)
1089 data_store.param_types.append(spin.params)
1090 data_store.gx.append(return_gyromagnetic_ratio(spin.heteronuc_type))
1091 data_store.gh.append(return_gyromagnetic_ratio(spin.proton_type))
1092 if sim_index == None or data_store.model_type == 'diff':
1093 data_store.r.append(spin.r)
1094 data_store.csa.append(spin.csa)
1095 else:
1096 data_store.r.append(spin.r_sim[sim_index])
1097 data_store.csa.append(spin.csa_sim[sim_index])
1098
1099
1100 if data_store.model_type == 'local_tm':
1101 pass
1102
1103
1104 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
1105 data_store.xh_unit_vectors.append(spin.xh_vect)
1106 else:
1107 data_store.xh_unit_vectors.append(None)
1108
1109
1110 data_store.num_params.append(len(spin.params))
1111
1112
1113 if data_store.model_type == 'diff':
1114 data_store.param_values.append(self._assemble_param_vector(model_type='mf'))
1115
1116
1117 for k in xrange(len(data_store.ri_data)):
1118 data_store.ri_data[k] = array(data_store.ri_data[k], float64)
1119 data_store.ri_data_err[k] = array(data_store.ri_data_err[k], float64)
1120
1121
1122 if data_store.model_type == 'local_tm':
1123 data_store.diff_type = 'sphere'
1124 else:
1125 data_store.diff_type = cdp.diff_tensor.type
1126
1127
1128 data_store.diff_params = None
1129 if data_store.model_type == 'mf':
1130
1131 if data_store.diff_type == 'sphere':
1132 data_store.diff_params = [cdp.diff_tensor.tm]
1133
1134
1135 elif data_store.diff_type == 'spheroid':
1136 data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi]
1137
1138
1139 elif data_store.diff_type == 'ellipsoid':
1140 data_store.diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.Dr, cdp.diff_tensor.alpha, cdp.diff_tensor.beta, cdp.diff_tensor.gamma]
1141 elif min_algor == 'back_calc' and data_store.model_type == 'local_tm':
1142
1143 data_store.diff_params = [spin.local_tm]
1144
1145
1147 """Package the relaxation data into the data structures used for optimisation.
1148
1149 @param spin: The spin container to extract the data from.
1150 @type spin: SpinContainer instance
1151 @keyword sim_index: The optional MC simulation index.
1152 @type sim_index: int
1153 @return: The structures ri_data, ri_data_err, num_frq, num_ri, ri_ids, frq, remap_table, noe_r1_table.
1154 @rtype: tuple
1155 """
1156
1157
1158 ri_data = []
1159 ri_data_err = []
1160 ri_labels = []
1161 frq = []
1162 remap_table = []
1163 noe_r1_table = []
1164
1165
1166 for ri_id in cdp.ri_ids:
1167
1168 if sim_index == None:
1169 data = spin.ri_data[ri_id]
1170 else:
1171 data = spin.ri_data_sim[ri_id][sim_index]
1172
1173
1174 err = spin.ri_data_err[ri_id]
1175
1176
1177 if data == None or err == None:
1178 continue
1179
1180
1181 ri_data.append(data)
1182 ri_data_err.append(err)
1183
1184
1185 ri_labels.append(cdp.ri_type[ri_id])
1186
1187
1188 if cdp.frq[ri_id] not in frq:
1189 frq.append(cdp.frq[ri_id])
1190
1191
1192 remap_table.append(frq.index(cdp.frq[ri_id]))
1193
1194
1195 noe_r1_table.append(None)
1196
1197
1198 num_ri = len(ri_data)
1199
1200
1201 for i in range(num_ri):
1202
1203 if cdp.ri_type[cdp.ri_ids[i]] == 'NOE':
1204 for j in range(num_ri):
1205 if cdp.ri_type[cdp.ri_ids[j]] == 'R1' and cdp.frq[cdp.ri_ids[i]] == cdp.frq[cdp.ri_ids[j]]:
1206 noe_r1_table[i] = j
1207
1208
1209 return ri_data, ri_data_err, len(frq), num_ri, ri_labels, frq, remap_table, noe_r1_table
1210
1211
1213 """Reset all the minimisation statistics.
1214
1215 All global and spin specific values will be set to None.
1216 """
1217
1218
1219 if hasattr(cdp, 'chi2'):
1220 cdp.chi2 = None
1221 cdp.iter = None
1222 cdp.f_count = None
1223 cdp.g_count = None
1224 cdp.h_count = None
1225 cdp.warning = None
1226
1227
1228 for spin in spin_loop():
1229 if hasattr(spin, 'chi2'):
1230 spin.chi2 = None
1231 spin.iter = None
1232 spin.f_count = None
1233 spin.g_count = None
1234 spin.h_count = None
1235 spin.warning = None
1236
1237
1238 - def calculate(self, spin_id=None, verbosity=1, sim_index=None):
1239 """Calculation of the model-free chi-squared value.
1240
1241 @keyword spin_id: The spin identification string.
1242 @type spin_id: str
1243 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
1244 @type verbosity: int
1245 @keyword sim_index: The optional MC simulation index.
1246 @type sim_index: int
1247 """
1248
1249
1250 if not exists_mol_res_spin_data():
1251 raise RelaxNoSequenceError
1252
1253
1254 model_type = self._determine_model_type()
1255
1256
1257 if model_type != 'local_tm' and not diff_data_exists():
1258 raise RelaxNoTensorError('diffusion')
1259
1260
1261 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and not hasattr(cdp, 'structure'):
1262 raise RelaxNoPdbError
1263
1264
1265 for spin, id in spin_loop(spin_id, return_id=True):
1266
1267 if not spin.select:
1268 continue
1269
1270
1271 if not spin.model:
1272 raise RelaxNoModelError
1273
1274
1275 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and not hasattr(spin, 'xh_vect'):
1276 raise RelaxNoVectorsError
1277
1278
1279 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere' and hasattr(spin, 'xh_vect') and arg_check.is_num_list(spin.xh_vect[0], raise_error=False):
1280 raise RelaxMultiVectorError
1281
1282
1283 if not hasattr(spin, 'heteronuc_type'):
1284 raise RelaxSpinTypeError
1285
1286
1287 if not hasattr(spin, 'proton_type'):
1288 raise RelaxProtonTypeError
1289
1290
1291 unset_param = self._are_mf_params_set(spin)
1292 if unset_param != None:
1293 raise RelaxNoValueError(unset_param)
1294
1295
1296 if not hasattr(spin, 'csa') or spin.csa == None:
1297 raise RelaxNoValueError("CSA")
1298
1299
1300 if not hasattr(spin, 'r') or spin.r == None:
1301 raise RelaxNoValueError("bond length")
1302
1303
1304 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
1305 continue
1306
1307
1308 for ri_id in cdp.ri_ids:
1309
1310 err = spin.ri_data_err[ri_id]
1311
1312
1313 if err != None and err == 0.0:
1314 raise RelaxError("Zero error for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (id, ri_id))
1315 elif err != None and err < 0.0:
1316 raise RelaxError("Negative error of %s for spin '%s' for the relaxation data ID '%s', minimisation not possible." % (err, id, ri_id))
1317
1318
1319 param_vector = self._assemble_param_vector(spin=spin, sim_index=sim_index)
1320
1321
1322 data = self._relax_data_opt_structs(spin, sim_index=sim_index)
1323
1324
1325 ri_data = [array(data[0])]
1326 ri_data_err = [array(data[1])]
1327 num_frq = [data[2]]
1328 num_ri = [data[3]]
1329 ri_labels = [data[4]]
1330 frq = [data[5]]
1331 remap_table = [data[6]]
1332 noe_r1_table = [data[7]]
1333
1334
1335 if sim_index == None:
1336 r = [spin.r]
1337 csa = [spin.csa]
1338 else:
1339 r = [spin.r_sim[sim_index]]
1340 csa = [spin.csa_sim[sim_index]]
1341
1342
1343 if model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
1344 xh_unit_vectors = [spin.xh_vect]
1345 else:
1346 xh_unit_vectors = [None]
1347
1348
1349 gx = [return_gyromagnetic_ratio(spin.heteronuc_type)]
1350 gh = [return_gyromagnetic_ratio(spin.proton_type)]
1351
1352
1353 num_params = [len(spin.params)]
1354
1355
1356 param_values = [self._assemble_param_vector(model_type='mf')]
1357
1358
1359 if model_type == 'local_tm':
1360 diff_params = [spin.local_tm]
1361 diff_type = 'sphere'
1362 else:
1363
1364 diff_type = cdp.diff_tensor.type
1365
1366
1367 if diff_type == 'sphere':
1368 diff_params = [cdp.diff_tensor.tm]
1369
1370
1371 elif diff_type == 'spheroid':
1372 diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.theta, cdp.diff_tensor.phi]
1373
1374
1375 elif diff_type == 'ellipsoid':
1376 diff_params = [cdp.diff_tensor.tm, cdp.diff_tensor.Da, cdp.diff_tensor.Dr, cdp.diff_tensor.alpha, cdp.diff_tensor.beta, cdp.diff_tensor.gamma]
1377
1378
1379 mf = Mf(init_params=param_vector, model_type='mf', diff_type=diff_type, diff_params=diff_params, num_spins=1, equations=[spin.equation], param_types=[spin.params], param_values=param_values, relax_data=ri_data, errors=ri_data_err, bond_length=r, csa=csa, num_frq=num_frq, frq=frq, num_ri=num_ri, remap_table=remap_table, noe_r1_table=noe_r1_table, ri_labels=ri_labels, gx=gx, gh=gh, h_bar=h_bar, mu0=mu0, num_params=num_params, vectors=xh_unit_vectors)
1380
1381
1382 try:
1383 chi2 = mf.func(param_vector)
1384 except OverflowError:
1385 chi2 = 1e200
1386
1387
1388 if model_type == 'all' or model_type == 'diff':
1389 cdp.chi2 = cdp.chi2 + chi2
1390 else:
1391 spin.chi2 = chi2
1392
1393
1394 - def grid_search(self, lower=None, upper=None, inc=None, constraints=True, verbosity=1, sim_index=None):
1395 """The model-free grid search function.
1396
1397 @keyword lower: The lower bounds of the grid search which must be equal to the
1398 number of parameters in the model.
1399 @type lower: array of numbers
1400 @keyword upper: The upper bounds of the grid search which must be equal to the
1401 number of parameters in the model.
1402 @type upper: array of numbers
1403 @keyword inc: The increments for each dimension of the space for the grid search.
1404 The number of elements in the array must equal to the number of
1405 parameters in the model.
1406 @type inc: array of int
1407 @keyword constraints: If True, constraints are applied during the grid search (eliminating
1408 parts of the grid). If False, no constraints are used.
1409 @type constraints: bool
1410 @keyword verbosity: A flag specifying the amount of information to print. The higher
1411 the value, the greater the verbosity.
1412 @type verbosity: int
1413 @keyword sim_index: The index of the simulation to apply the grid search to. If None,
1414 the normal model is optimised.
1415 @type sim_index: int
1416 """
1417
1418
1419 self.minimise(min_algor='grid', lower=lower, upper=upper, inc=inc, constraints=constraints, verbosity=verbosity, sim_index=sim_index)
1420
1421
1422 - def minimise(self, min_algor=None, min_options=None, func_tol=None, grad_tol=None, max_iterations=None, constraints=False, scaling=True, verbosity=0, sim_index=None, lower=None, upper=None, inc=None):
1423 """Model-free minimisation function.
1424
1425 Three categories of models exist for which the approach to minimisation is different. These
1426 are:
1427
1428 Single spin optimisations: The 'mf' and 'local_tm' model types which are the
1429 model-free parameters for single spins, optionally with a local tm parameter. These
1430 models have no global parameters.
1431
1432 Diffusion tensor optimisations: The 'diff' diffusion tensor model type. No spin
1433 specific parameters exist.
1434
1435 Optimisation of everything: The 'all' model type consisting of all model-free and all
1436 diffusion tensor parameters.
1437
1438
1439 @keyword min_algor: The minimisation algorithm to use.
1440 @type min_algor: str
1441 @keyword min_options: An array of options to be used by the minimisation algorithm.
1442 @type min_options: array of str
1443 @keyword func_tol: The function tolerance which, when reached, terminates optimisation.
1444 Setting this to None turns of the check.
1445 @type func_tol: None or float
1446 @keyword grad_tol: The gradient tolerance which, when reached, terminates optimisation.
1447 Setting this to None turns of the check.
1448 @type grad_tol: None or float
1449 @keyword max_iterations: The maximum number of iterations for the algorithm.
1450 @type max_iterations: int
1451 @keyword constraints: If True, constraints are used during optimisation.
1452 @type constraints: bool
1453 @keyword scaling: If True, diagonal scaling is enabled during optimisation to allow
1454 the problem to be better conditioned.
1455 @type scaling: bool
1456 @keyword verbosity: The amount of information to print. The higher the value, the
1457 greater the verbosity.
1458 @type verbosity: int
1459 @keyword sim_index: The index of the simulation to optimise. This should be None if
1460 normal optimisation is desired.
1461 @type sim_index: None or int
1462 @keyword lower: The lower bounds of the grid search which must be equal to the
1463 number of parameters in the model. This optional argument is only
1464 used when doing a grid search.
1465 @type lower: array of numbers
1466 @keyword upper: The upper bounds of the grid search which must be equal to the
1467 number of parameters in the model. This optional argument is only
1468 used when doing a grid search.
1469 @type upper: array of numbers
1470 @keyword inc: The increments for each dimension of the space for the grid search.
1471 The number of elements in the array must equal to the number of
1472 parameters in the model. This argument is only used when doing a
1473 grid search.
1474 @type inc: array of int
1475 """
1476
1477
1478 if not exists_mol_res_spin_data():
1479 raise RelaxNoSequenceError
1480
1481
1482 for spin in spin_loop():
1483
1484 if not spin.select:
1485 continue
1486
1487
1488 if not spin.model:
1489 raise RelaxNoModelError
1490
1491
1492 if not hasattr(spin, 'heteronuc_type'):
1493 raise RelaxSpinTypeError
1494
1495
1496 if not hasattr(spin, 'proton_type'):
1497 raise RelaxProtonTypeError
1498
1499
1500 if sim_index == None and min_algor != 'back_calc':
1501 self._reset_min_stats()
1502
1503
1504 data_store = Data_container()
1505 opt_params = Data_container()
1506
1507
1508 data_store.h_bar = h_bar
1509 data_store.mu0 = mu0
1510 opt_params.min_algor = min_algor
1511 opt_params.min_options = min_options
1512 opt_params.func_tol = func_tol
1513 opt_params.grad_tol = grad_tol
1514 opt_params.max_iterations = max_iterations
1515
1516
1517 opt_params.verbosity = verbosity
1518
1519
1520 data_store.model_type = self._determine_model_type()
1521 if not data_store.model_type:
1522 return
1523
1524
1525 if min_algor == 'back_calc' and data_store.model_type != 'local_tm':
1526 data_store.model_type = 'mf'
1527
1528
1529 if data_store.model_type != 'local_tm' and not diffusion_tensor.diff_data_exists():
1530 raise RelaxNoTensorError('diffusion')
1531
1532
1533 if data_store.model_type != 'local_tm' and cdp.diff_tensor.type != 'sphere':
1534
1535 if not hasattr(cdp, 'structure'):
1536 raise RelaxNoPdbError
1537
1538
1539 for spin in spin_loop():
1540
1541 if not spin.select:
1542 continue
1543
1544
1545 if not hasattr(spin, 'xh_vect'):
1546 raise RelaxNoVectorsError
1547
1548
1549 if data_store.model_type == 'diff':
1550
1551 for spin in spin_loop():
1552 unset_param = self._are_mf_params_set(spin)
1553 if unset_param != None:
1554 raise RelaxNoValueError(unset_param)
1555
1556
1557 if verbosity >= 1:
1558 if data_store.model_type == 'mf':
1559 print("Only the model-free parameters for single spins will be used.")
1560 elif data_store.model_type == 'local_mf':
1561 print("Only a local tm value together with the model-free parameters for single spins will be used.")
1562 elif data_store.model_type == 'diff':
1563 print("Only diffusion tensor parameters will be used.")
1564 elif data_store.model_type == 'all':
1565 print("The diffusion tensor parameters together with the model-free parameters for all spins will be used.")
1566
1567
1568 for spin in spin_loop():
1569
1570 if not spin.select:
1571 continue
1572
1573
1574 if not hasattr(spin, 'csa') or spin.csa == None:
1575 raise RelaxNoValueError("CSA")
1576
1577
1578 if not hasattr(spin, 'r') or spin.r == None:
1579 raise RelaxNoValueError("bond length")
1580
1581
1582 if data_store.model_type == 'mf' or data_store.model_type == 'local_tm':
1583 num_instances = count_spins(skip_desel=False)
1584 num_data_sets = 1
1585 data_store.num_spins = 1
1586 elif data_store.model_type == 'diff' or data_store.model_type == 'all':
1587 num_instances = 1
1588 num_data_sets = count_spins(skip_desel=False)
1589 data_store.num_spins = count_spins()
1590
1591
1592 if min_algor == 'back_calc':
1593 num_instances = 1
1594 num_data_sets = 0
1595 data_store.num_spins = 1
1596
1597
1598 processor_box = Processor_box()
1599 processor = processor_box.processor
1600
1601
1602
1603
1604 for i in xrange(num_instances):
1605
1606 if data_store.model_type == 'diff' or data_store.model_type == 'all':
1607 spin_index = None
1608 spin, data_store.spin_id = None, None
1609 elif min_algor == 'back_calc':
1610 spin_index = opt_params.min_options[0]
1611 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
1612 else:
1613 spin_index = i
1614 spin, data_store.spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
1615
1616
1617 if spin and (data_store.model_type == 'mf' or data_store.model_type == 'local_tm') and not min_algor == 'back_calc':
1618
1619 if not spin.select:
1620 continue
1621
1622
1623 if not hasattr(spin, 'ri_data') or not hasattr(spin, 'ri_data_err'):
1624 continue
1625
1626
1627 if min_algor == 'back_calc':
1628
1629 opt_params.param_vector = self._assemble_param_vector(spin=spin, model_type=data_store.model_type)
1630
1631
1632 data_store.scaling_matrix = None
1633
1634 else:
1635
1636 opt_params.param_vector = self._assemble_param_vector(spin=spin, sim_index=sim_index)
1637
1638
1639 num_params = len(opt_params.param_vector)
1640
1641
1642 data_store.scaling_matrix = self._assemble_scaling_matrix(num_params, model_type=data_store.model_type, spin=spin, scaling=scaling)
1643 if len(data_store.scaling_matrix):
1644 opt_params.param_vector = dot(inv(data_store.scaling_matrix), opt_params.param_vector)
1645
1646
1647 opt_params.inc, opt_params.lower, opt_params.upper = None, None, None
1648 if match('^[Gg]rid', min_algor):
1649 opt_params.inc, opt_params.lower, opt_params.upper = self._grid_search_config(num_params, spin=spin, lower=lower, upper=upper, inc=inc, scaling_matrix=data_store.scaling_matrix)
1650
1651
1652 if match('^[Ss]et', min_algor):
1653 opt_params.min_options = dot(inv(data_store.scaling_matrix), opt_params.min_options)
1654
1655
1656 if constraints:
1657 opt_params.A, opt_params.b = self._linear_constraints(num_params, model_type=data_store.model_type, spin=spin, scaling_matrix=data_store.scaling_matrix)
1658 else:
1659 opt_params.A, opt_params.b = None, None
1660
1661
1662 self._minimise_data_setup(data_store, min_algor, num_data_sets, opt_params.min_options, spin=spin, sim_index=sim_index)
1663
1664
1665 if constraints and not match('^[Gg]rid', min_algor):
1666 algor = opt_params.min_options[0]
1667 else:
1668 algor = min_algor
1669
1670
1671 if min_algor == 'back_calc' or match('[Ll][Mm]$', algor) or match('[Ll]evenburg-[Mm]arquardt$', algor):
1672 self.mf = Mf(init_params=opt_params.param_vector, model_type=data_store.model_type, diff_type=data_store.diff_type, diff_params=data_store.diff_params, scaling_matrix=data_store.scaling_matrix, num_spins=data_store.num_spins, equations=data_store.equations, param_types=data_store.param_types, param_values=data_store.param_values, relax_data=data_store.ri_data, errors=data_store.ri_data_err, bond_length=data_store.r, csa=data_store.csa, num_frq=data_store.num_frq, frq=data_store.frq, num_ri=data_store.num_ri, remap_table=data_store.remap_table, noe_r1_table=data_store.noe_r1_table, ri_labels=data_store.ri_types, gx=data_store.gx, gh=data_store.gh, h_bar=data_store.h_bar, mu0=data_store.mu0, num_params=data_store.num_params, vectors=data_store.xh_unit_vectors)
1673
1674
1675 if match('[Ll][Mm]$', algor) or match('[Ll]evenburg-[Mm]arquardt$', algor):
1676
1677 number_ri = 0
1678 for k in xrange(len(ri_data_err)):
1679 number_ri = number_ri + len(ri_data_err[k])
1680
1681
1682 lm_error = zeros(number_ri, float64)
1683 index = 0
1684 for k in xrange(len(ri_data_err)):
1685 lm_error[index:index+len(ri_data_err[k])] = ri_data_err[k]
1686 index = index + len(ri_data_err[k])
1687
1688 opt_params.min_options = opt_params.min_options + (self.mf.lm_dri, lm_error)
1689
1690
1691 if min_algor == 'back_calc':
1692 return self.mf.calc_ri()
1693
1694
1695 if match('^[Gg]rid', min_algor) and data_store.model_type == 'diff':
1696
1697 print("Parallelised diffusion tensor grid search.")
1698
1699
1700 for subdivision in grid_split(divisions=processor.processor_size(), lower=opt_params.lower, upper=opt_params.upper, inc=opt_params.inc):
1701
1702 opt_params.subdivision = subdivision
1703
1704
1705 command = MF_grid_command()
1706
1707
1708 command.store_data(deepcopy(data_store), deepcopy(opt_params))
1709
1710
1711 memo = MF_memo(model_free=self, model_type=data_store.model_type, spin=spin, sim_index=sim_index, scaling=scaling, scaling_matrix=data_store.scaling_matrix)
1712 processor.add_to_queue(command, memo)
1713
1714
1715 processor.run_queue()
1716
1717
1718 return
1719
1720
1721 if search('^[Gg]rid', min_algor):
1722 command = MF_grid_command()
1723
1724
1725 else:
1726 command = MF_minimise_command()
1727
1728
1729 command.store_data(deepcopy(data_store), deepcopy(opt_params))
1730
1731
1732 memo = MF_memo(model_free=self, model_type=data_store.model_type, spin=spin, sim_index=sim_index, scaling=scaling, scaling_matrix=data_store.scaling_matrix)
1733 processor.add_to_queue(command, memo)
1734
1735
1736 processor.run_queue()
1737