1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for the optimisation of the frame order models."""
24
25
26 from math import cos, pi
27 from minfx.generic import generic_minimise
28 from minfx.grid import grid_point_array
29 from numpy import arccos, array, dot, float64, ndarray, ones, zeros
30 from numpy.linalg import inv, norm
31 import sys
32 from warnings import warn
33
34
35 from lib.check_types import is_float
36 from lib.float import isNaN, isInf
37 from lib.errors import RelaxError, RelaxInfError, RelaxNaNError, RelaxNoPCSError, RelaxNoRDCError
38 from lib.frame_order.pseudo_ellipse import tmax_pseudo_ellipse_array
39 from lib.frame_order.variables import MODEL_DOUBLE_ROTOR, MODEL_FREE_ROTOR, MODEL_ISO_CONE, MODEL_ISO_CONE_FREE_ROTOR, MODEL_ISO_CONE_TORSIONLESS, MODEL_LIST_FREE_ROTORS, MODEL_LIST_PSEUDO_ELLIPSE, MODEL_PSEUDO_ELLIPSE, MODEL_PSEUDO_ELLIPSE_FREE_ROTOR, MODEL_PSEUDO_ELLIPSE_TORSIONLESS, MODEL_RIGID, MODEL_ROTOR
40 from lib.geometry.angles import wrap_angles
41 from lib.periodic_table import periodic_table
42 from lib.physical_constants import dipolar_constant
43 from lib.warnings import RelaxWarning
44 from multi import Memo, Result_command, Slave_command
45 from pipe_control.interatomic import interatomic_loop
46 from pipe_control.mol_res_spin import return_spin, spin_loop
47 from pipe_control.structure.mass import pipe_centre_of_mass
48 from specific_analyses.frame_order.checks import check_domain, check_model, check_parameters
49 from specific_analyses.frame_order.data import base_data_types, domain_moving, pivot_fixed, tensor_loop
50 from specific_analyses.frame_order.parameters import assemble_param_vector, linear_constraints
51 from target_functions.frame_order import Frame_order, sobol_data
52
53
55 """Count the number of Sobol' points for the current parameter values of the model.
56
57 The count will be stored in the current data pipe and printed out.
58
59
60 @keyword target_fn: The pre-initialised frame order target function class.
61 @type target_fn: target_functions.frame_order.Frame_order instance
62 @keyword verbosity: If greater than 0, lots of information will be printed out.
63 @type verbosity: int
64 """
65
66
67 if verbosity:
68 print("\nSobol' quasi-random integration point counting for the current parameter values.")
69
70
71 if not check_model(escalate=1):
72 return
73 if not check_parameters(escalate=1):
74 return
75 if not check_domain(escalate=1):
76 return
77
78
79 if cdp.model == MODEL_RIGID:
80 if verbosity:
81 print("Sobol' quasi-random integration points are not used for the rigid frame order model.\n")
82 return
83
84
85 if target_fn == None:
86
87 param_vector, full_tensors, full_in_ref_frame, rdcs, rdc_err, rdc_weight, rdc_vect, rdc_const, pcs, pcs_err, pcs_weight, atomic_pos, temp, frq, paramag_centre, com, ave_pos_pivot, pivot, pivot_opt = target_fn_data_setup(verbosity=0, unset_fail=True)
88
89
90 if not hasattr(cdp, 'quad_int'):
91 cdp.quad_int = False
92 sobol_max_points, sobol_oversample = None, None
93 if hasattr(cdp, 'sobol_max_points'):
94 sobol_max_points = cdp.sobol_max_points
95 sobol_oversample = cdp.sobol_oversample
96
97
98 target_fn = Frame_order(model=cdp.model, init_params=param_vector, full_tensors=full_tensors, full_in_ref_frame=full_in_ref_frame, rdcs=rdcs, rdc_errors=rdc_err, rdc_weights=rdc_weight, rdc_vect=rdc_vect, dip_const=rdc_const, pcs=pcs, pcs_errors=pcs_err, pcs_weights=pcs_weight, atomic_pos=atomic_pos, temp=temp, frq=frq, paramag_centre=paramag_centre, scaling_matrix=None, com=com, ave_pos_pivot=ave_pos_pivot, pivot=pivot, pivot_opt=pivot_opt, sobol_max_points=sobol_max_points, sobol_oversample=sobol_oversample, quad_int=cdp.quad_int)
99
100
101 if cdp.model in [MODEL_ISO_CONE, MODEL_ISO_CONE_FREE_ROTOR, MODEL_PSEUDO_ELLIPSE, MODEL_PSEUDO_ELLIPSE_FREE_ROTOR]:
102 dims = ['theta', 'phi', 'sigma']
103 elif cdp.model in [MODEL_ISO_CONE_TORSIONLESS, MODEL_PSEUDO_ELLIPSE_TORSIONLESS]:
104 dims = ['theta', 'phi']
105 elif cdp.model in [MODEL_ROTOR, MODEL_FREE_ROTOR]:
106 dims = ['sigma']
107 elif cdp.model in [MODEL_DOUBLE_ROTOR]:
108 dims = ['sigma', 'sigma2']
109
110
111 theta, phi, sigma, sigma2 = None, None, None, None
112 if dims == ['theta', 'phi', 'sigma']:
113 theta, phi, sigma = sobol_data.sobol_angles
114 elif dims == ['theta', 'phi']:
115 theta, phi = sobol_data.sobol_angles
116 elif dims == ['sigma']:
117 sigma = sobol_data.sobol_angles[0]
118 elif dims == ['sigma', 'sigma2']:
119 sigma, sigma2 = sobol_data.sobol_angles
120
121
122 pe = False
123 if cdp.model in MODEL_LIST_PSEUDO_ELLIPSE:
124 pe = True
125
126
127 theta_max = tmax_pseudo_ellipse_array(phi, cdp.cone_theta_x, cdp.cone_theta_y)
128
129
130 if cdp.model in MODEL_LIST_FREE_ROTORS:
131 cone_sigma_max = pi
132 elif 'sigma' in dims:
133 cone_sigma_max = cdp.cone_sigma_max
134
135
136 if not pe and 'theta' in dims:
137 cone_theta = cdp.cone_theta
138
139
140 total_num = len(sobol_data.sobol_angles[0])
141 count = 0
142 for i in range(total_num):
143
144 if pe and theta[i] > theta_max[i]:
145 continue
146
147
148 if not pe and 'theta' in dims and theta[i] > cone_theta:
149 continue
150
151
152 if 'sigma' in dims and abs(sigma[i]) > cone_sigma_max:
153 continue
154
155
156 if 'sigma2' in dims and abs(sigma2[i]) > cdp.cone_sigma_max_2:
157 continue
158
159
160 count += 1
161
162
163 if count == cdp.sobol_max_points:
164 break
165
166
167 cdp.sobol_points_used = count
168
169
170 if verbosity:
171 format = " %-30s %20s\n"
172 percent = "%s" % (float(count)/float(cdp.sobol_max_points)*100) + '%'
173 sys.stdout.write(format % ("Maximum number of points:", cdp.sobol_max_points))
174 sys.stdout.write(format % ("Oversampling factor:", cdp.sobol_oversample))
175 sys.stdout.write(format % ("Total points:", total_num))
176 sys.stdout.write(format % ("Used points:", count))
177 sys.stdout.write(format % ("Percentage:", percent))
178 sys.stdout.write('\n')
179
180
181 -def grid_row(incs, lower, upper, dist_type=None, end_point=True):
182 """Set up a row of the grid search for a given parameter.
183
184 @param incs: The number of increments.
185 @type incs: int
186 @param lower: The lower bounds.
187 @type lower: float
188 @param upper: The upper bounds.
189 @type upper: float
190 @keyword dist_type: The spacing or distribution type between grid nodes. If None, then a linear grid row is returned. If 'acos', then an inverse cos distribution of points is returned (e.g. for uniform sampling in angular space).
191 @type dist_type: None or str
192 @keyword end_point: A flag which if False will cause the end point to be removed.
193 @type end_point: bool
194 @return: The row of the grid.
195 @rtype: list of float
196 """
197
198
199 row = []
200
201
202 if dist_type == None:
203
204 if incs == 1:
205 row.append((lower + upper) / 2.0)
206
207
208 else:
209 for i in range(incs):
210 row.append(lower + i * (upper - lower) / (incs - 1.0))
211
212
213 elif dist_type == 'acos':
214
215 if incs == 1:
216 row.append((lower + upper) / 2.0)
217
218
219 else:
220 v = zeros(incs, float64)
221 val = (cos(lower) - cos(upper)) / (incs - 1.0)
222 for i in range(incs):
223 v[-i-1] = cos(upper) + float(i) * val
224
225
226 row = arccos(v)
227
228
229 if incs != 1 and not end_point:
230 row = row[:-1]
231
232
233 return list(row)
234
235
237 """Set up the atomic position data structures for optimisation using PCSs and PREs as base data sets.
238
239 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
240 @type sim_index: None or int
241 @keyword verbosity: If set to 1 or higher, then printouts and warnings will be active.
242 @type verbosity: int
243 @return: The atomic positions (the first index is the spins, the second is the structures, and the third is the atomic coordinates) and the paramagnetic centre.
244 @rtype: numpy rank-3 array, numpy rank-1 array.
245 """
246
247
248 atomic_pos = []
249
250
251 ave_warning_spin_ids = []
252 ave_warning_num = None
253 for spin, spin_id in spin_loop(selection=domain_moving(), return_id=True):
254
255 if not spin.select:
256 continue
257
258
259 if not hasattr(spin, 'pcs') and not hasattr(spin, 'pre'):
260 continue
261
262
263 if (isinstance(spin.pos, list) or isinstance(spin.pos, ndarray)) and len(spin.pos) == 3 and is_float(spin.pos[0]):
264 atomic_pos.append(spin.pos)
265
266
267 else:
268
269 if sim_index == None:
270 ave_warning_spin_ids.append(spin_id)
271 if ave_warning_num == None:
272 ave_warning_num = len(spin.pos)
273 elif ave_warning_num != len(spin.pos):
274 ave_warning_num = 'multiple'
275
276
277 ave_pos = zeros(3, float64)
278 count = 0
279 for i in range(len(spin.pos)):
280 if spin.pos[i] is None:
281 continue
282 ave_pos += spin.pos[i]
283 count += 1
284 ave_pos = ave_pos / float(count)
285
286
287 atomic_pos.append(ave_pos)
288
289
290 if verbosity and ave_warning_num != 1 and len(ave_warning_spin_ids):
291 warn(RelaxWarning("Averaging the %s atomic positions for the PCS for the spins %s." % (ave_warning_num, ave_warning_spin_ids)))
292
293
294 atomic_pos = array(atomic_pos, float64)
295
296
297 if not hasattr(cdp, 'paramagnetic_centre'):
298 paramag_centre = zeros(3, float64)
299 else:
300 paramag_centre = array(cdp.paramagnetic_centre)
301
302
303 return atomic_pos, paramag_centre
304
305
307 """Set up the data structures for optimisation using PCSs as base data sets.
308
309 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
310 @type sim_index: None or int
311 @return: The assembled data structures for using PCSs as the base data for optimisation. These include:
312 - the PCS values.
313 - the unit vectors connecting the paramagnetic centre (the electron spin) to
314 - the PCS weight.
315 - the nuclear spin.
316 - the pseudocontact shift constants.
317 @rtype: tuple of (numpy rank-2 array, numpy rank-2 array, numpy rank-2 array, numpy rank-1 array, numpy rank-1 array)
318 """
319
320
321 if not hasattr(cdp, 'paramagnetic_centre'):
322 raise RelaxError("The paramagnetic centre has not yet been specified.")
323 if not hasattr(cdp, 'temperature'):
324 raise RelaxError("The experimental temperatures have not been set.")
325 if not hasattr(cdp, 'spectrometer_frq'):
326 raise RelaxError("The spectrometer frequencies of the experiments have not been set.")
327
328
329 pcs = []
330 pcs_err = []
331 pcs_weight = []
332 temp = []
333 frq = []
334
335
336 for i in range(len(cdp.align_ids)):
337
338 align_id = cdp.align_ids[i]
339
340
341 if not opt_uses_align_data(align_id):
342 continue
343
344
345 pcs.append([])
346 pcs_err.append([])
347 pcs_weight.append([])
348
349
350 if align_id in cdp.temperature:
351 temp.append(cdp.temperature[align_id])
352
353
354 else:
355 raise RelaxError("The experimental temperature for the alignment ID '%s' has not been set." % align_id)
356
357
358 if align_id in cdp.spectrometer_frq:
359 frq.append(cdp.spectrometer_frq[align_id] * 2.0 * pi / periodic_table.gyromagnetic_ratio('1H'))
360
361
362 else:
363 raise RelaxError("The spectrometer frequency for the alignment ID '%s' has not been set." % align_id)
364
365
366 j = 0
367 for spin in spin_loop(selection=domain_moving()):
368
369 if not spin.select:
370 continue
371
372
373 if not hasattr(spin, 'pcs'):
374 continue
375
376
377 if align_id in spin.pcs:
378 if sim_index != None:
379 pcs[-1].append(spin.pcs_sim[align_id][sim_index])
380 else:
381 pcs[-1].append(spin.pcs[align_id])
382 else:
383 pcs[-1].append(None)
384
385
386 if hasattr(spin, 'pcs_err') and align_id in spin.pcs_err:
387 pcs_err[-1].append(spin.pcs_err[align_id])
388 else:
389 pcs_err[-1].append(None)
390
391
392 if hasattr(spin, 'pcs_weight') and align_id in spin.pcs_weight:
393 pcs_weight[-1].append(spin.pcs_weight[align_id])
394 else:
395 pcs_weight[-1].append(1.0)
396
397
398 j = j + 1
399
400
401 pcs = array(pcs, float64)
402 pcs_err = array(pcs_err, float64)
403 pcs_weight = array(pcs_weight, float64)
404
405
406 pcs = pcs * 1e-6
407 pcs_err = pcs_err * 1e-6
408
409
410 return pcs, pcs_err, pcs_weight, temp, frq
411
412
414 """Set up the data structures for optimisation using RDCs as base data sets.
415
416 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
417 @type sim_index: None or int
418 @return: The assembled data structures for using RDCs as the base data for optimisation. These include:
419 - rdc, the RDC values.
420 - rdc_err, the RDC errors.
421 - rdc_weight, the RDC weights.
422 - vectors, the interatomic vectors.
423 - rdc_const, the dipolar constants.
424 - absolute, the absolute value flags (as 1's and 0's).
425 @rtype: tuple of (numpy rank-2 array, numpy rank-2 array, numpy rank-2 array, numpy rank-3 array, numpy rank-2 array, numpy rank-2 array)
426 """
427
428
429 rdc = []
430 rdc_err = []
431 rdc_weight = []
432 unit_vect = []
433 rdc_const = []
434 absolute = []
435
436
437 for interatom in interatomic_loop(selection1=domain_moving()):
438
439 spin1 = return_spin(spin_hash=interatom._spin_hash1)
440 spin2 = return_spin(spin_hash=interatom._spin_hash2)
441
442
443 if interatom.vector.shape == (3,):
444 unit_vect.append(interatom.vector)
445
446
447 else:
448
449 if sim_index == None:
450 warn(RelaxWarning("Averaging the %s unit vectors for the RDC for the spin pair '%s' and '%s'." % (len(interatom.vector), interatom.spin_id1, interatom.spin_id2)))
451
452
453 ave_vector = zeros(3, float64)
454 for i in range(len(interatom.vector)):
455 ave_vector += interatom.vector[i]
456
457
458 unit_vect.append(ave_vector)
459
460
461 unit_vect[-1] = unit_vect[-1] / norm(unit_vect[-1])
462
463
464 g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
465 g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)
466
467
468 rdc_const.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r))
469
470
471 num = None
472 for rdc_index in range(len(unit_vect)):
473
474 if num == None:
475 if unit_vect[rdc_index] is not None:
476 num = len(unit_vect[rdc_index])
477 continue
478
479
480 if unit_vect[rdc_index] is not None and len(unit_vect[rdc_index]) != num:
481 raise RelaxError("The number of interatomic vectors for all no match:\n%s" % unit_vect)
482
483
484 if num == None:
485 raise RelaxError("No interatomic vectors could be found.")
486
487
488 for i in range(len(unit_vect)):
489 if unit_vect[i] is None:
490 unit_vect[i] = [[None, None, None]]*num
491
492
493 for i in range(len(cdp.align_ids)):
494
495 align_id = cdp.align_ids[i]
496
497
498 if not opt_uses_align_data(align_id):
499 continue
500
501
502 rdc.append([])
503 rdc_err.append([])
504 rdc_weight.append([])
505 absolute.append([])
506
507
508 for interatom in interatomic_loop(domain_moving(), skip_desel=True):
509
510 spin1 = return_spin(spin_hash=interatom._spin_hash1)
511 spin2 = return_spin(spin_hash=interatom._spin_hash2)
512
513
514 if not hasattr(interatom, 'rdc') or not hasattr(interatom, 'vector'):
515 continue
516
517
518 value = None
519 error = None
520
521
522 if (hasattr(spin1, 'members') or hasattr(spin2, 'members')) and align_id in interatom.rdc:
523 raise RelaxError("Psuedo-atoms are currently not supported for the frame order analysis.")
524
525
526 elif align_id in interatom.rdc:
527
528 if sim_index != None:
529 value = interatom.rdc_sim[align_id][sim_index]
530 else:
531 value = interatom.rdc[align_id]
532
533
534 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err:
535 error = interatom.rdc_err[align_id]
536
537
538 rdc[-1].append(value)
539
540
541 rdc_err[-1].append(error)
542
543
544 if hasattr(interatom, 'rdc_weight') and align_id in interatom.rdc_weight:
545 rdc_weight[-1].append(interatom.rdc_weight[align_id])
546 else:
547 rdc_weight[-1].append(1.0)
548
549
550 if hasattr(interatom, 'absolute_rdc') and align_id in interatom.absolute_rdc:
551 absolute[-1].append(interatom.absolute_rdc[align_id])
552 else:
553 absolute[-1].append(False)
554
555
556 rdc = array(rdc, float64)
557 rdc_err = array(rdc_err, float64)
558 rdc_weight = array(rdc_weight, float64)
559 unit_vect = array(unit_vect, float64)
560 rdc_const = array(rdc_const, float64)
561 absolute = array(absolute, float64)
562
563
564 return rdc, rdc_err, rdc_weight, unit_vect, rdc_const, absolute
565
566
568 """Set up the data structures for optimisation using alignment tensors as base data sets.
569
570 @keyword sim_index: The simulation index. This should be None if normal optimisation is desired.
571 @type sim_index: None or int
572 @return: The assembled data structures for using alignment tensors as the base data for optimisation. These include:
573 - full_tensors, the full tensors as concatenated arrays.
574 - full_err, the full tensor errors as concatenated arrays.
575 - full_in_ref_frame, the flags specifying if the tensor is the full or reduced tensor in the non-moving reference domain.
576 @rtype: tuple of 3 numpy nx5D, rank-1 arrays
577 """
578
579
580 if not hasattr(cdp, 'ref_domain'):
581 raise RelaxError("The reference non-moving domain has not been specified.")
582 if not hasattr(cdp.align_tensors, 'reduction'):
583 raise RelaxError("The tensor reductions have not been specified.")
584 for i, tensor in tensor_loop():
585 if not hasattr(tensor, 'domain'):
586 raise RelaxError("The domain that the '%s' tensor is attached to has not been set" % tensor.name)
587
588
589 n = len(cdp.align_tensors.reduction)
590 full_tensors = zeros(n*5, float64)
591 full_err = ones(n*5, float64) * 1e-5
592 full_in_ref_frame = zeros(n, float64)
593
594
595 for i, tensor in tensor_loop(red=False):
596
597 full_tensors[5*i + 0] = tensor.Axx
598 full_tensors[5*i + 1] = tensor.Ayy
599 full_tensors[5*i + 2] = tensor.Axy
600 full_tensors[5*i + 3] = tensor.Axz
601 full_tensors[5*i + 4] = tensor.Ayz
602
603
604 if cdp.ref_domain == tensor.domain:
605 full_in_ref_frame[i] = 1
606
607
608 if hasattr(tensor, 'Axx_err'):
609 full_err[5*i + 0] = tensor.Axx_err
610 full_err[5*i + 1] = tensor.Ayy_err
611 full_err[5*i + 2] = tensor.Axy_err
612 full_err[5*i + 3] = tensor.Axz_err
613 full_err[5*i + 4] = tensor.Ayz_err
614
615
616 return full_tensors, full_err, full_in_ref_frame
617
618
620 """Determine if the PCS or RDC data for the given alignment ID is needed for optimisation.
621
622 @keyword align_id: The optional alignment ID string.
623 @type align_id: str
624 @return: True if alignment data is to be used for optimisation, False otherwise.
625 @rtype: bool
626 """
627
628
629 if not hasattr(cdp, 'align_ids'):
630 return False
631
632
633 if align_id:
634 align_ids = [align_id]
635 else:
636 align_ids = cdp.align_ids
637
638
639 for align_id in align_ids:
640 if opt_uses_pcs(align_id) or opt_uses_rdc(align_id):
641 return True
642
643
644 return False
645
646
648 """Determine if the PCS data for the given alignment ID is needed for optimisation.
649
650 @param align_id: The alignment ID string.
651 @type align_id: str
652 @return: True if the PCS data is to be used for optimisation, False otherwise.
653 @rtype: bool
654 """
655
656
657 if not hasattr(cdp, 'pcs_ids'):
658 return False
659
660
661 if align_id not in cdp.pcs_ids:
662 return False
663
664
665 return True
666
667
669 """Determine if the RDC data for the given alignment ID is needed for optimisation.
670
671 @param align_id: The alignment ID string.
672 @type align_id: str
673 @return: True if the RDC data is to be used for optimisation, False otherwise.
674 @rtype: bool
675 """
676
677
678 if not hasattr(cdp, 'rdc_ids'):
679 return False
680
681
682 if align_id not in cdp.rdc_ids:
683 return False
684
685
686 return True
687
688
690 """Store the back-calculated data.
691
692 @keyword A_5D_bc: The reduced back-calculated alignment tensors from the target function.
693 @type A_5D_bc: numpy float64 array
694 @keyword pcs_theta: The back calculated PCS values from the target function.
695 @type pcs_theta: numpy float64 array
696 @keyword rdc_theta: The back calculated RDC values from the target function.
697 @type rdc_theta: numpy float64 array
698 """
699
700
701 for i, tensor in tensor_loop(red=True):
702
703 tensor.set(param='Axx', value=A_5D_bc[5*i + 0])
704 tensor.set(param='Ayy', value=A_5D_bc[5*i + 1])
705 tensor.set(param='Axy', value=A_5D_bc[5*i + 2])
706 tensor.set(param='Axz', value=A_5D_bc[5*i + 3])
707 tensor.set(param='Ayz', value=A_5D_bc[5*i + 4])
708
709
710 for i in range(len(cdp.align_ids)):
711
712 align_id = cdp.align_ids[i]
713
714
715 rdc_flag = False
716 if hasattr(cdp, 'rdc_ids') and align_id in cdp.rdc_ids:
717 rdc_flag = True
718 pcs_flag = False
719 if hasattr(cdp, 'pcs_ids') and align_id in cdp.pcs_ids:
720 pcs_flag = True
721
722
723 pcs_index = 0
724 for spin in spin_loop(domain_moving()):
725
726 if not spin.select:
727 continue
728
729
730 if pcs_flag and hasattr(spin, 'pcs'):
731
732 if not hasattr(spin, 'pcs_bc'):
733 spin.pcs_bc = {}
734
735
736 spin.pcs_bc[align_id] = pcs_theta[i, pcs_index] * 1e6
737
738
739 pcs_index += 1
740
741
742 rdc_index = 0
743 for interatom in interatomic_loop(domain_moving(), skip_desel=True):
744
745 if not hasattr(interatom, 'rdc_bc'):
746 interatom.rdc_bc = {}
747
748
749 interatom.rdc_bc[align_id] = rdc_theta[i, rdc_index]
750
751
752 rdc_index += 1
753
754
756 """Initialise the target function for optimisation or direct calculation.
757
758 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
759 @type sim_index: None or int
760 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
761 @type verbosity: int
762 @keyword scaling_matrix: The diagonal and square scaling matrices.
763 @type scaling_matrix: numpy rank-2, float64 array or None
764 @keyword unset_fail: A flag which if True will cause a RelaxError to be raised if the parameter is not set yet.
765 @type unset_fail: bool
766 """
767
768
769 if verbosity:
770 print("Frame order model: %s" % cdp.model)
771
772
773 param_vector = assemble_param_vector(sim_index=sim_index, unset_fail=unset_fail)
774
775
776 data_types = base_data_types()
777
778
779 if scaling_matrix != None and len(param_vector):
780 param_vector = dot(inv(scaling_matrix), param_vector)
781
782
783 full_tensors, full_tensor_err, full_in_ref_frame = minimise_setup_tensors(sim_index)
784
785
786 pcs, pcs_err, pcs_weight, temp, frq = None, None, None, None, None
787 if 'pcs' in data_types:
788 pcs, pcs_err, pcs_weight, temp, frq = minimise_setup_pcs(sim_index=sim_index)
789
790
791 rdcs, rdc_err, rdc_weight, rdc_vect, rdc_const, absolute_rdc = None, None, None, None, None, None
792 if 'rdc' in data_types:
793 rdcs, rdc_err, rdc_weight, rdc_vect, rdc_const, absolute_rdc = minimise_setup_rdcs(sim_index=sim_index)
794
795
796 if pcs is not None and not len(pcs):
797 raise RelaxNoPCSError
798 if rdcs is not None and not len(rdcs):
799 raise RelaxNoRDCError
800
801
802 atomic_pos, paramag_centre = None, None
803 if 'pcs' in data_types or 'pre' in data_types:
804 atomic_pos, paramag_centre = minimise_setup_atomic_pos(sim_index=sim_index, verbosity=verbosity)
805
806
807 pivot = None
808 if hasattr(cdp, 'pivot_x'):
809 pivot = array([cdp.pivot_x, cdp.pivot_y, cdp.pivot_z])
810
811
812 pivot_opt = True
813 if pivot_fixed():
814 pivot_opt = False
815
816
817 ave_pos_pivot = pipe_centre_of_mass(atom_id=domain_moving(), verbosity=0)
818
819
820 com = None
821 if cdp.model in [MODEL_ROTOR, MODEL_FREE_ROTOR, MODEL_DOUBLE_ROTOR]:
822
823 com = pipe_centre_of_mass(verbosity=0)
824 com = array(com, float64)
825
826
827 if verbosity and sim_index == None:
828 sys.stdout.write("\nThe average domain rotation centroid, taken as the CoM of the atoms defined as the moving domain, is:\n %s\n" % list(ave_pos_pivot))
829 if com is not None:
830 sys.stdout.write("The centre of mass reference coordinate for the rotor models is:\n %s\n" % list(com))
831 if cdp.model != MODEL_RIGID:
832 if hasattr(cdp, 'quad_int') and cdp.quad_int:
833 sys.stdout.write("Numerical PCS integration: SciPy quadratic integration.\n")
834 else:
835 sys.stdout.write("Numerical PCS integration: Quasi-random Sobol' sequence.\n")
836 base_data = []
837 if rdcs is not None and len(rdcs):
838 base_data.append("RDCs")
839 if pcs is not None and len(pcs):
840 base_data.append("PCSs")
841 sys.stdout.write("Base data: %s\n" % repr(base_data))
842 sys.stdout.write("\n")
843
844
845 return param_vector, full_tensors, full_in_ref_frame, rdcs, rdc_err, rdc_weight, rdc_vect, rdc_const, pcs, pcs_err, pcs_weight, atomic_pos, temp, frq, paramag_centre, com, ave_pos_pivot, pivot, pivot_opt
846
847
848 -def unpack_opt_results(param_vector=None, func=None, iter_count=None, f_count=None, g_count=None, h_count=None, warning=None, scaling_matrix=None, sim_index=None):
849 """Unpack and store the Frame Order optimisation results.
850
851 @keyword param_vector: The model-free parameter vector.
852 @type param_vector: numpy array
853 @keyword func: The optimised chi-squared value.
854 @type func: float
855 @keyword iter_count: The number of optimisation steps required to find the minimum.
856 @type iter_count: int
857 @keyword f_count: The function count.
858 @type f_count: int
859 @keyword g_count: The gradient count.
860 @type g_count: int
861 @keyword h_count: The Hessian count.
862 @type h_count: int
863 @keyword warning: Any optimisation warnings.
864 @type warning: str or None
865 @keyword scaling_matrix: The diagonal and square scaling matrices.
866 @type scaling_matrix: numpy rank-2, float64 array or None
867 @keyword sim_index: The index of the simulation to optimise. This should be None for normal optimisation.
868 @type sim_index: None or int
869 """
870
871
872 if isInf(func):
873 raise RelaxInfError('chi-squared')
874
875
876 if isNaN(func):
877 raise RelaxNaNError('chi-squared')
878
879
880 if scaling_matrix is not None:
881 param_vector = dot(scaling_matrix, param_vector)
882
883
884 wrap = [
885 'ave_pos_alpha',
886 'ave_pos_beta',
887 'ave_pos_gamma',
888 'eigen_alpha',
889 'eigen_beta',
890 'eigen_gamma',
891 'axis_theta',
892 'axis_phi'
893 ]
894
895
896 if sim_index != None:
897
898 for i in range(len(cdp.params)):
899
900 if cdp.params[i] in wrap or cdp.params[i] == 'axis_alpha':
901 val = getattr(cdp, cdp.params[i])
902 param_vector[i] = wrap_angles(param_vector[i], val-pi, val+pi)
903
904
905 obj = getattr(cdp, cdp.params[i]+'_sim')
906 obj[sim_index] = param_vector[i]
907
908
909 cdp.chi2_sim[sim_index] = func
910 cdp.iter_sim[sim_index] = iter_count
911 cdp.f_count_sim[sim_index] = f_count
912 cdp.g_count_sim[sim_index] = g_count
913 cdp.h_count_sim[sim_index] = h_count
914 cdp.warning_sim[sim_index] = warning
915
916
917 else:
918
919 for i in range(len(cdp.params)):
920
921 if cdp.params[i] in wrap:
922 param_vector[i] = wrap_angles(param_vector[i], 0.0, 2.0*pi)
923 if cdp.params[i] == 'axis_alpha':
924 param_vector[i] = wrap_angles(param_vector[i], -pi, pi)
925
926
927 setattr(cdp, cdp.params[i], param_vector[i])
928
929
930 cdp.chi2 = func
931 cdp.iter = iter_count
932 cdp.f_count = f_count
933 cdp.g_count = g_count
934 cdp.h_count = h_count
935 cdp.warning = warning
936
937
938
940 """Command class for relaxation dispersion optimisation on the slave processor."""
941
942 - def __init__(self, points=None, scaling_matrix=None, sim_index=None, model=None, param_vector=None, full_tensors=None, full_in_ref_frame=None, rdcs=None, rdc_err=None, rdc_weight=None, rdc_vect=None, rdc_const=None, pcs=None, pcs_err=None, pcs_weight=None, atomic_pos=None, temp=None, frq=None, paramag_centre=None, com=None, ave_pos_pivot=None, pivot=None, pivot_opt=None, sobol_max_points=None, sobol_oversample=None, verbosity=None, quad_int=False):
943 """Initialise the base class, storing all the master data to be sent to the slave processor.
944
945 This method is run on the master processor whereas the run() method is run on the slave processor.
946
947 @keyword points: The points of the grid search subdivision to search over.
948 @type points: numpy rank-2 array
949 @keyword scaling_matrix: The diagonal, square scaling matrix.
950 @type scaling_matrix: numpy diagonal matrix
951 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
952 @type sim_index: None or int
953 @keyword model: The name of the Frame Order model.
954 @type model: str
955 @keyword param_vector: The initial parameter values.
956 @type param_vector: numpy float64 array
957 @keyword full_tensors: An array of the {Axx, Ayy, Axy, Axz, Ayz} values for all full alignment tensors. The format is [Axx1, Ayy1, Axy1, Axz1, Ayz1, Axx2, Ayy2, Axy2, Axz2, Ayz2, ..., Axxn, Ayyn, Axyn, Axzn, Ayzn].
958 @type full_tensors: numpy nx5D, rank-1 float64 array
959 @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor.
960 @type full_in_ref_frame: numpy rank-1 array
961 @keyword rdcs: The RDC lists. The first index must correspond to the different alignment media i and the second index to the spin systems j.
962 @type rdcs: numpy rank-2 array
963 @keyword rdc_err: The RDC error lists. The dimensions of this argument are the same as for 'rdcs'.
964 @type rdc_err: numpy rank-2 array
965 @keyword rdc_weight: The RDC weight lists. The dimensions of this argument are the same as for 'rdcs'.
966 @type rdc_weight: numpy rank-2 array
967 @keyword rdc_vect: The unit XH vector lists corresponding to the RDC values. The first index must correspond to the spin systems and the second index to the x, y, z elements.
968 @type rdc_vect: numpy rank-2 array
969 @keyword rdc_const: The dipolar constants for each RDC. The indices correspond to the spin systems j.
970 @type rdc_const: numpy rank-1 array
971 @keyword pcs: The PCS lists. The first index must correspond to the different alignment media i and the second index to the spin systems j.
972 @type pcs: numpy rank-2 array
973 @keyword pcs_err: The PCS error lists. The dimensions of this argument are the same as for 'pcs'.
974 @type pcs_err: numpy rank-2 array
975 @keyword pcs_weight: The PCS weight lists. The dimensions of this argument are the same as for 'pcs'.
976 @type pcs_weight: numpy rank-2 array
977 @keyword atomic_pos: The atomic positions of all spins for the PCS and PRE data. The first index is the spin systems j and the second is the structure or state c.
978 @type atomic_pos: numpy rank-3 array
979 @keyword temp: The temperature of each PCS data set.
980 @type temp: numpy rank-1 array
981 @keyword frq: The frequency of each PCS data set.
982 @type frq: numpy rank-1 array
983 @keyword paramag_centre: The paramagnetic centre position (or positions).
984 @type paramag_centre: numpy rank-1, 3D array or rank-2, Nx3 array
985 @keyword com: The centre of mass of the system. This is used for defining the rotor model systems.
986 @type com: numpy 3D rank-1 array
987 @keyword ave_pos_pivot: The pivot point to rotate all atoms about to the average domain position. In most cases this will be the centre of mass of the moving domain. This pivot is shifted by the translation vector.
988 @type ave_pos_pivot: numpy 3D rank-1 array
989 @keyword pivot: The pivot point for the ball-and-socket joint motion. This is needed if PCS or PRE values are used.
990 @type pivot: numpy rank-1, 3D array or None
991 @keyword pivot_opt: A flag which if True will allow the pivot point of the motion to be optimised.
992 @type pivot_opt: bool
993 @keyword sobol_max_points: The maximum number of Sobol' points to use for the numerical PCS integration technique.
994 @type sobol_max_points: int
995 @keyword sobol_oversample: The oversampling factor Ov used for the total number of points N * Ov * 10**M, where N is the maximum number of Sobol' points and M is the number of dimensions or torsion-tilt angles for the system.
996 @type sobol_oversample: int
997 @keyword verbosity: The verbosity level. This is used by the result command returned to the master for printouts.
998 @type verbosity: int
999 @keyword quad_int: A flag which if True will perform high precision numerical integration via the scipy.integrate quad(), dblquad() and tplquad() integration methods rather than the rough quasi-random numerical integration.
1000 @type quad_int: bool
1001 """
1002
1003
1004 self.points = points
1005 self.scaling_matrix = scaling_matrix
1006 self.model = model
1007 self.param_vector = param_vector
1008 self.full_tensors = full_tensors
1009 self.full_in_ref_frame = full_in_ref_frame
1010 self.rdcs = rdcs
1011 self.rdc_err = rdc_err
1012 self.rdc_weight = rdc_weight
1013 self.rdc_vect = rdc_vect
1014 self.rdc_const = rdc_const
1015 self.pcs = pcs
1016 self.pcs_err = pcs_err
1017 self.pcs_weight = pcs_weight
1018 self.atomic_pos = atomic_pos
1019 self.temp = temp
1020 self.frq = frq
1021 self.paramag_centre = paramag_centre
1022 self.com = com
1023 self.ave_pos_pivot = ave_pos_pivot
1024 self.pivot = pivot
1025 self.pivot_opt = pivot_opt
1026 self.sobol_max_points = sobol_max_points
1027 self.sobol_oversample = sobol_oversample
1028 self.verbosity = verbosity
1029 self.quad_int = quad_int
1030
1031
1032 - def run(self, processor, completed):
1033 """Set up and perform the optimisation."""
1034
1035
1036 target_fn = Frame_order(model=self.model, init_params=self.param_vector, full_tensors=self.full_tensors, full_in_ref_frame=self.full_in_ref_frame, rdcs=self.rdcs, rdc_errors=self.rdc_err, rdc_weights=self.rdc_weight, rdc_vect=self.rdc_vect, dip_const=self.rdc_const, pcs=self.pcs, pcs_errors=self.pcs_err, pcs_weights=self.pcs_weight, atomic_pos=self.atomic_pos, temp=self.temp, frq=self.frq, paramag_centre=self.paramag_centre, scaling_matrix=self.scaling_matrix, com=self.com, ave_pos_pivot=self.ave_pos_pivot, pivot=self.pivot, pivot_opt=self.pivot_opt, sobol_max_points=self.sobol_max_points, sobol_oversample=self.sobol_oversample, quad_int=self.quad_int)
1037
1038
1039 results = grid_point_array(func=target_fn.func, args=(), points=self.points, verbosity=self.verbosity)
1040
1041
1042 processor.return_object(Frame_order_result_command(processor=processor, memo_id=self.memo_id, results=results, A_5D_bc=target_fn.A_5D_bc, pcs_theta=target_fn.pcs_theta, rdc_theta=target_fn.rdc_theta, completed=completed))
1043
1044
1045
1047 """The frame order memo class."""
1048
1049 - def __init__(self, spins=None, spin_ids=None, sim_index=None, scaling_matrix=None, verbosity=None):
1050 """Initialise the relaxation dispersion memo class.
1051
1052 This is used for handling the optimisation results returned from a slave processor. It runs on the master processor and is used to store data which is passed to the slave processor and then passed back to the master via the results command.
1053
1054
1055 @keyword spins: The list of spin data container for the cluster. If this argument is supplied, then the spin_id argument will be ignored.
1056 @type spins: list of SpinContainer instances
1057 @keyword spin_ids: The spin ID strings for the cluster.
1058 @type spin_ids: list of str
1059 @keyword sim_index: The optional MC simulation index.
1060 @type sim_index: int
1061 @keyword scaling_matrix: The diagonal, square scaling matrix.
1062 @type scaling_matrix: numpy diagonal matrix
1063 @keyword verbosity: The verbosity level. This is used by the result command returned to the master for printouts.
1064 @type verbosity: int
1065 """
1066
1067
1068 super(Frame_order_memo, self).__init__()
1069
1070
1071 self.spins = spins
1072 self.spin_ids = spin_ids
1073 self.sim_index = sim_index
1074 self.scaling_matrix = scaling_matrix
1075
1076
1077
1079 """Command class for relaxation dispersion optimisation on the slave processor."""
1080
1081 - def __init__(self, min_algor=None, min_options=None, func_tol=None, grad_tol=None, max_iterations=None, scaling_matrix=None, constraints=False, sim_index=None, model=None, param_vector=None, full_tensors=None, full_in_ref_frame=None, rdcs=None, rdc_err=None, rdc_weight=None, rdc_vect=None, rdc_const=None, pcs=None, pcs_err=None, pcs_weight=None, atomic_pos=None, temp=None, frq=None, paramag_centre=None, com=None, ave_pos_pivot=None, pivot=None, pivot_opt=None, sobol_max_points=None, sobol_oversample=None, verbosity=None, quad_int=False):
1082 """Initialise the base class, storing all the master data to be sent to the slave processor.
1083
1084 This method is run on the master processor whereas the run() method is run on the slave processor.
1085
1086 @keyword min_algor: The minimisation algorithm to use.
1087 @type min_algor: str
1088 @keyword min_options: An array of options to be used by the minimisation algorithm.
1089 @type min_options: array of str
1090 @keyword func_tol: The function tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
1091 @type func_tol: None or float
1092 @keyword grad_tol: The gradient tolerance which, when reached, terminates optimisation. Setting this to None turns of the check.
1093 @type grad_tol: None or float
1094 @keyword max_iterations: The maximum number of iterations for the algorithm.
1095 @type max_iterations: int
1096 @keyword constraints: If True, constraints are used during optimisation.
1097 @type constraints: bool
1098 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
1099 @type sim_index: None or int
1100 @keyword model: The name of the Frame Order model.
1101 @type model: str
1102 @keyword param_vector: The initial parameter values.
1103 @type param_vector: numpy float64 array
1104 @keyword full_tensors: An array of the {Axx, Ayy, Axy, Axz, Ayz} values for all full alignment tensors. The format is [Axx1, Ayy1, Axy1, Axz1, Ayz1, Axx2, Ayy2, Axy2, Axz2, Ayz2, ..., Axxn, Ayyn, Axyn, Axzn, Ayzn].
1105 @type full_tensors: numpy nx5D, rank-1 float64 array
1106 @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor.
1107 @type full_in_ref_frame: numpy rank-1 array
1108 @keyword rdcs: The RDC lists. The first index must correspond to the different alignment media i and the second index to the spin systems j.
1109 @type rdcs: numpy rank-2 array
1110 @keyword rdc_err: The RDC error lists. The dimensions of this argument are the same as for 'rdcs'.
1111 @type rdc_err: numpy rank-2 array
1112 @keyword rdc_weight: The RDC weight lists. The dimensions of this argument are the same as for 'rdcs'.
1113 @type rdc_weight: numpy rank-2 array
1114 @keyword rdc_vect: The unit XH vector lists corresponding to the RDC values. The first index must correspond to the spin systems and the second index to the x, y, z elements.
1115 @type rdc_vect: numpy rank-2 array
1116 @keyword rdc_const: The dipolar constants for each RDC. The indices correspond to the spin systems j.
1117 @type rdc_const: numpy rank-1 array
1118 @keyword pcs: The PCS lists. The first index must correspond to the different alignment media i and the second index to the spin systems j.
1119 @type pcs: numpy rank-2 array
1120 @keyword pcs_err: The PCS error lists. The dimensions of this argument are the same as for 'pcs'.
1121 @type pcs_err: numpy rank-2 array
1122 @keyword pcs_weight: The PCS weight lists. The dimensions of this argument are the same as for 'pcs'.
1123 @type pcs_weight: numpy rank-2 array
1124 @keyword atomic_pos: The atomic positions of all spins for the PCS and PRE data. The first index is the spin systems j and the second is the structure or state c.
1125 @type atomic_pos: numpy rank-3 array
1126 @keyword temp: The temperature of each PCS data set.
1127 @type temp: numpy rank-1 array
1128 @keyword frq: The frequency of each PCS data set.
1129 @type frq: numpy rank-1 array
1130 @keyword paramag_centre: The paramagnetic centre position (or positions).
1131 @type paramag_centre: numpy rank-1, 3D array or rank-2, Nx3 array
1132 @keyword com: The centre of mass of the system. This is used for defining the rotor model systems.
1133 @type com: numpy 3D rank-1 array
1134 @keyword ave_pos_pivot: The pivot point to rotate all atoms about to the average domain position. In most cases this will be the centre of mass of the moving domain. This pivot is shifted by the translation vector.
1135 @type ave_pos_pivot: numpy 3D rank-1 array
1136 @keyword pivot: The pivot point for the ball-and-socket joint motion. This is needed if PCS or PRE values are used.
1137 @type pivot: numpy rank-1, 3D array or None
1138 @keyword pivot_opt: A flag which if True will allow the pivot point of the motion to be optimised.
1139 @type pivot_opt: bool
1140 @keyword sobol_max_points: The maximum number of Sobol' points to use for the numerical PCS integration technique.
1141 @type sobol_max_points: int
1142 @keyword sobol_oversample: The oversampling factor Ov used for the total number of points N * Ov * 10**M, where N is the maximum number of Sobol' points and M is the number of dimensions or torsion-tilt angles for the system.
1143 @type sobol_oversample: int
1144 @keyword scaling_matrix: The diagonal, square scaling matrix.
1145 @type scaling_matrix: numpy diagonal matrix
1146 @keyword quad_int: A flag which if True will perform high precision numerical integration via the scipy.integrate quad(), dblquad() and tplquad() integration methods rather than the rough quasi-random numerical integration.
1147 @type quad_int: bool
1148 """
1149
1150
1151 self.min_algor = min_algor
1152 self.min_options = min_options
1153 self.func_tol = func_tol
1154 self.grad_tol = grad_tol
1155 self.max_iterations = max_iterations
1156 self.scaling_matrix = scaling_matrix
1157 self.model = model
1158 self.param_vector = param_vector
1159 self.full_tensors = full_tensors
1160 self.full_in_ref_frame = full_in_ref_frame
1161 self.rdcs = rdcs
1162 self.rdc_err = rdc_err
1163 self.rdc_weight = rdc_weight
1164 self.rdc_vect = rdc_vect
1165 self.rdc_const = rdc_const
1166 self.pcs = pcs
1167 self.pcs_err = pcs_err
1168 self.pcs_weight = pcs_weight
1169 self.atomic_pos = atomic_pos
1170 self.temp = temp
1171 self.frq = frq
1172 self.paramag_centre = paramag_centre
1173 self.com = com
1174 self.ave_pos_pivot = ave_pos_pivot
1175 self.pivot = pivot
1176 self.pivot_opt = pivot_opt
1177 self.sobol_max_points = sobol_max_points
1178 self.sobol_oversample = sobol_oversample
1179 self.verbosity = verbosity
1180 self.quad_int = quad_int
1181
1182
1183 target_fn = Frame_order(model=self.model, init_params=self.param_vector, full_tensors=self.full_tensors, full_in_ref_frame=self.full_in_ref_frame, rdcs=self.rdcs, rdc_errors=self.rdc_err, rdc_weights=self.rdc_weight, rdc_vect=self.rdc_vect, dip_const=self.rdc_const, pcs=self.pcs, pcs_errors=self.pcs_err, pcs_weights=self.pcs_weight, atomic_pos=self.atomic_pos, temp=self.temp, frq=self.frq, paramag_centre=self.paramag_centre, scaling_matrix=self.scaling_matrix, com=self.com, ave_pos_pivot=self.ave_pos_pivot, pivot=self.pivot, pivot_opt=self.pivot_opt, sobol_max_points=self.sobol_max_points, sobol_oversample=self.sobol_oversample, quad_int=self.quad_int)
1184 if not self.quad_int:
1185 count_sobol_points(target_fn=target_fn, verbosity=self.verbosity)
1186
1187
1188 self.A, self.b = None, None
1189 if constraints:
1190
1191 self.A, self.b = linear_constraints(scaling_matrix=scaling_matrix)
1192
1193
1194 if self.A is None:
1195 if verbosity:
1196 warn(RelaxWarning("The '%s' model parameters are not constrained, turning the linear constraint algorithm off." % cdp.model))
1197
1198
1199 if self.min_algor == 'Log barrier':
1200 self.min_algor = self.min_options[0]
1201 self.min_options = self.min_options[1:]
1202
1203
1204 - def run(self, processor, completed):
1205 """Set up and perform the optimisation."""
1206
1207
1208 target_fn = Frame_order(model=self.model, init_params=self.param_vector, full_tensors=self.full_tensors, full_in_ref_frame=self.full_in_ref_frame, rdcs=self.rdcs, rdc_errors=self.rdc_err, rdc_weights=self.rdc_weight, rdc_vect=self.rdc_vect, dip_const=self.rdc_const, pcs=self.pcs, pcs_errors=self.pcs_err, pcs_weights=self.pcs_weight, atomic_pos=self.atomic_pos, temp=self.temp, frq=self.frq, paramag_centre=self.paramag_centre, scaling_matrix=self.scaling_matrix, com=self.com, ave_pos_pivot=self.ave_pos_pivot, pivot=self.pivot, pivot_opt=self.pivot_opt, sobol_max_points=self.sobol_max_points, sobol_oversample=self.sobol_oversample, quad_int=self.quad_int)
1209
1210
1211 results = generic_minimise(func=target_fn.func, args=(), x0=self.param_vector, min_algor=self.min_algor, min_options=self.min_options, func_tol=self.func_tol, grad_tol=self.grad_tol, maxiter=self.max_iterations, A=self.A, b=self.b, full_output=True, print_flag=self.verbosity)
1212
1213
1214 processor.return_object(Frame_order_result_command(processor=processor, memo_id=self.memo_id, results=results, A_5D_bc=target_fn.A_5D_bc, pcs_theta=target_fn.pcs_theta, rdc_theta=target_fn.rdc_theta, completed=completed))
1215
1216
1217
1219 """Class for processing the frame order results.
1220
1221 This object will be sent from the slave back to the master to have its run() method executed.
1222 """
1223
1224 - def __init__(self, processor=None, memo_id=None, results=None, A_5D_bc=None, pcs_theta=None, rdc_theta=None, completed=False):
1225 """Set up the class, placing the minimisation results here.
1226
1227 @keyword processor: The processor object.
1228 @type processor: multi.processor.Processor instance
1229 @keyword memo_id: The memo identification string.
1230 @type memo_id: str
1231 @keyword results: The results as returned by minfx.
1232 @type results: tuple
1233 @keyword A_5D_bc: The reduced back-calculated alignment tensors from the target function.
1234 @type A_5D_bc: numpy float64 array
1235 @keyword pcs_theta: The back calculated PCS values from the target function.
1236 @type pcs_theta: numpy float64 array
1237 @keyword rdc_theta: The back calculated RDC values from the target function.
1238 @type rdc_theta: numpy float64 array
1239 @keyword model: The target function class instance which has been optimised.
1240 @type model: class instance
1241 @keyword completed: A flag which if True signals that the optimisation successfully completed.
1242 @type completed: bool
1243 """
1244
1245
1246 super(Frame_order_result_command, self).__init__(processor=processor, completed=completed)
1247
1248
1249 self.memo_id = memo_id
1250 self.results = results
1251 self.A_5D_bc = A_5D_bc
1252 self.pcs_theta = pcs_theta
1253 self.rdc_theta = rdc_theta
1254
1255
1256 - def run(self, processor, memo):
1257 """Disassemble the frame order optimisation results.
1258
1259 @param processor: Unused!
1260 @type processor: None
1261 @param memo: The model-free memo.
1262 @type memo: memo
1263 """
1264
1265
1266 if memo.sim_index != None:
1267 print("Simulation %i" % (memo.sim_index+1))
1268
1269
1270 if len(self.results) == 4:
1271 param_vector, func, iter_count, warning = self.results
1272 f_count = iter_count
1273 g_count = 0.0
1274 h_count = 0.0
1275 else:
1276 param_vector, func, iter_count, f_count, g_count, h_count, warning = self.results
1277
1278
1279 if memo.sim_index == None:
1280 if hasattr(cdp, 'chi2') and cdp.chi2 != None:
1281
1282 if func > cdp.chi2:
1283 print("Discarding the optimisation results, the optimised chi-squared value is higher than the current value (%s > %s)." % (func, cdp.chi2))
1284 return
1285
1286
1287 print("Storing the optimisation results, the optimised chi-squared value is lower than the current value (%s < %s)." % (func, cdp.chi2))
1288
1289
1290 else:
1291 print("Storing the optimisation results, no optimised values currently exist.")
1292
1293
1294 unpack_opt_results(param_vector, func, iter_count, f_count, g_count, h_count, warning, memo.scaling_matrix, memo.sim_index)
1295
1296
1297 store_bc_data(A_5D_bc=self.A_5D_bc, pcs_theta=self.pcs_theta, rdc_theta=self.rdc_theta)
1298