1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module containing the target functions of the Frame Order theories."""
24
25
26 from copy import deepcopy
27 from math import acos, pi, sqrt
28 from numpy import array, dot, float32, float64, ones, transpose, uint8, zeros
29 from numpy.linalg import norm
30
31
32 from extern.sobol.sobol_lib import i4_sobol
33 from lib.alignment.alignment_tensor import to_5D, to_tensor
34 from lib.alignment.pcs import pcs_tensor
35 from lib.alignment.rdc import rdc_tensor
36 from lib.errors import RelaxError
37 from lib.float import isNaN
38 from lib.frame_order.double_rotor import compile_2nd_matrix_double_rotor, pcs_numeric_int_double_rotor
39 from lib.frame_order.free_rotor import compile_2nd_matrix_free_rotor
40 from lib.frame_order.iso_cone import compile_2nd_matrix_iso_cone, pcs_numeric_int_iso_cone, pcs_numeric_int_iso_cone_qrint
41 from lib.frame_order.iso_cone_free_rotor import compile_2nd_matrix_iso_cone_free_rotor
42 from lib.frame_order.iso_cone_torsionless import compile_2nd_matrix_iso_cone_torsionless, pcs_numeric_int_iso_cone_torsionless, pcs_numeric_int_iso_cone_torsionless_qrint
43 from lib.frame_order.matrix_ops import reduce_alignment_tensor
44 from lib.frame_order.pseudo_ellipse import compile_2nd_matrix_pseudo_ellipse, pcs_numeric_int_pseudo_ellipse, pcs_numeric_int_pseudo_ellipse_qrint
45 from lib.frame_order.pseudo_ellipse_free_rotor import compile_2nd_matrix_pseudo_ellipse_free_rotor
46 from lib.frame_order.pseudo_ellipse_torsionless import compile_2nd_matrix_pseudo_ellipse_torsionless, pcs_numeric_int_pseudo_ellipse_torsionless, pcs_numeric_int_pseudo_ellipse_torsionless_qrint
47 from lib.frame_order.rotor import compile_2nd_matrix_rotor, pcs_numeric_int_rotor, pcs_numeric_int_rotor_qrint
48 from lib.frame_order.rotor_axis import create_rotor_axis_alpha
49 from lib.geometry.coord_transform import spherical_to_cartesian
50 from lib.geometry.rotations import euler_to_R_zyz, two_vect_to_R
51 from lib.linear_algebra.kronecker_product import kron_prod
52 from lib.order import order_parameters
53 from lib.physical_constants import pcs_constant
54 from target_functions.chi2 import chi2
55
56
58 """Class containing the target function of the optimisation of Frame Order matrix components."""
59
60 - def __init__(self, model=None, init_params=None, full_tensors=None, full_in_ref_frame=None, rdcs=None, rdc_errors=None, rdc_weights=None, rdc_vect=None, dip_const=None, pcs=None, pcs_errors=None, pcs_weights=None, atomic_pos=None, temp=None, frq=None, paramag_centre=zeros(3), scaling_matrix=None, num_int_pts=500, com=None, ave_pos_pivot=zeros(3), ave_pos_piv_sync=True, translation_opt=False, pivot=None, pivot2=None, pivot_opt=False, quad_int=True):
61 """Set up the target functions for the Frame Order theories.
62
63 @keyword model: The name of the Frame Order model.
64 @type model: str
65 @keyword init_params: The initial parameter values.
66 @type init_params: numpy float64 array
67 @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].
68 @type full_tensors: numpy nx5D, rank-1 float64 array
69 @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor.
70 @type full_in_ref_frame: numpy rank-1 array
71 @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.
72 @type rdcs: numpy rank-2 array
73 @keyword rdc_errors: The RDC error lists. The dimensions of this argument are the same as for 'rdcs'.
74 @type rdc_errors: numpy rank-2 array
75 @keyword rdc_weights: The RDC weight lists. The dimensions of this argument are the same as for 'rdcs'.
76 @type rdc_weights: numpy rank-2 array
77 @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.
78 @type rdc_vect: numpy rank-2 array
79 @keyword dip_const: The dipolar constants for each RDC. The indices correspond to the spin systems j.
80 @type dip_const: numpy rank-1 array
81 @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.
82 @type pcs: numpy rank-2 array
83 @keyword pcs_errors: The PCS error lists. The dimensions of this argument are the same as for 'pcs'.
84 @type pcs_errors: numpy rank-2 array
85 @keyword pcs_weights: The PCS weight lists. The dimensions of this argument are the same as for 'pcs'.
86 @type pcs_weights: numpy rank-2 array
87 @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.
88 @type atomic_pos: numpy rank-3 array
89 @keyword temp: The temperature of each PCS data set.
90 @type temp: numpy rank-1 array
91 @keyword frq: The frequency of each PCS data set.
92 @type frq: numpy rank-1 array
93 @keyword paramag_centre: The paramagnetic centre position (or positions).
94 @type paramag_centre: numpy rank-1, 3D array or rank-2, Nx3 array
95 @keyword scaling_matrix: The square and diagonal scaling matrix.
96 @type scaling_matrix: numpy rank-2 array
97 @keyword num_int_pts: The number of points to use for the numerical integration technique.
98 @type num_int_pts: int
99 @keyword com: The centre of mass of the system. This is used for defining the rotor model systems.
100 @type com: numpy 3D rank-1 array
101 @keyword ave_pos_pivot: The pivot point to rotate all atoms about to the average domain position. For example this can be the centre of mass of the moving domain.
102 @type ave_pos_pivot: numpy 3D rank-1 array
103 @keyword ave_pos_piv_sync: A flag which if True will cause pivot point to rotate to the average domain position to be synchronised with the motional pivot. This will cause ave_pos_pivot argument to be ignored.
104 @type ave_pos_piv_sync: bool
105 @keyword translation_opt: A flag which if True will allow the pivot point of the motion to be optimised.
106 @type translation_opt: bool
107 @keyword pivot: The pivot point for the ball-and-socket joint motion. This is needed if PCS or PRE values are used.
108 @type pivot: numpy rank-1, 3D array or None
109 @keyword pivot2: The second pivot point for the motion. This is needed if PCS or PRE values are used and if a double-motional model is to be optimised.
110 @type pivot2: numpy rank-1, 3D array or None
111 @keyword pivot_opt: A flag which if True will allow the pivot point of the motion to be optimised.
112 @type pivot_opt: bool
113 @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.
114 @type quad_int: bool
115 """
116
117
118 if not model:
119 raise RelaxError("The type of Frame Order model must be specified.")
120
121
122 self.params = deepcopy(init_params)
123
124
125 self.model = model
126 self.full_tensors = full_tensors
127 self.full_in_ref_frame = full_in_ref_frame
128 self.rdc = rdcs
129 self.rdc_weights = rdc_weights
130 self.rdc_vect = rdc_vect
131 self.dip_const = dip_const
132 self.pcs = pcs
133 self.pcs_weights = pcs_weights
134 self.atomic_pos = atomic_pos
135 self.temp = temp
136 self.frq = frq
137 self.paramag_centre = paramag_centre
138 self.total_num_params = len(init_params)
139 self.num_int_pts = num_int_pts
140 self.com = com
141 self.ave_pos_pivot = ave_pos_pivot
142 self.ave_pos_piv_sync = ave_pos_piv_sync
143 self.translation_opt = translation_opt
144 self._param_pivot = pivot
145 self._param_pivot2 = pivot2
146 self.pivot_opt = pivot_opt
147
148
149 self._init_tensors()
150
151
152 self.scaling_matrix = scaling_matrix
153 if self.scaling_matrix != None:
154 self.scaling_flag = True
155 else:
156 self.scaling_flag = False
157
158
159 self.num_align = 0
160 if rdcs != None:
161 self.num_align = len(rdcs)
162 elif pcs != None:
163 self.num_align = len(pcs)
164
165
166 self.rdc_flag = [True] * self.num_align
167 self.pcs_flag = [True] * self.num_align
168 for align_index in range(self.num_align):
169 if rdcs == None or len(rdcs[align_index]) == 0:
170 self.rdc_flag[align_index] = False
171 if pcs == None or len(pcs[align_index]) == 0:
172 self.pcs_flag[align_index] = False
173 self.rdc_flag_sum = sum(self.rdc_flag)
174 self.pcs_flag_sum = sum(self.pcs_flag)
175
176
177 self._translation_vector = zeros(3, float64)
178
179
180 if self.rdc_flag_sum and (rdc_vect == None or not len(rdc_vect)):
181 raise RelaxError("The rdc_vect argument " + repr(rdc_vect) + " must be supplied.")
182 if self.pcs_flag_sum and (atomic_pos == None or not len(atomic_pos)):
183 raise RelaxError("The atomic_pos argument " + repr(atomic_pos) + " must be supplied.")
184
185
186 self.num_spins = 0
187 if self.pcs_flag_sum:
188 self.num_spins = len(pcs[0])
189
190
191 self.num_interatom = 0
192 if self.rdc_flag_sum:
193 self.num_interatom = len(rdcs[0])
194
195
196 for align_index in range(self.num_align):
197 to_tensor(self.A_3D[align_index], self.full_tensors[5*align_index:5*align_index+5])
198
199
200 if self.pcs_flag_sum:
201 err = False
202 for i in range(len(pcs_errors)):
203 for j in range(len(pcs_errors[i])):
204 if not isNaN(pcs_errors[i, j]):
205 err = True
206 if err:
207 self.pcs_error = pcs_errors
208 else:
209
210 self.pcs_error = 0.1 * 1e-6 * ones((self.num_align, self.num_spins), float64)
211
212
213 if self.rdc_flag_sum:
214 err = False
215 for i in range(len(rdc_errors)):
216 for j in range(len(rdc_errors[i])):
217 if not isNaN(rdc_errors[i, j]):
218 err = True
219 if err:
220 self.rdc_error = rdc_errors
221 else:
222
223 self.rdc_error = ones((self.num_align, self.num_interatom), float64)
224
225
226 if self.rdc_flag_sum:
227 self.missing_rdc = zeros((self.num_align, self.num_interatom), uint8)
228
229
230 if self.pcs_flag_sum:
231 self.missing_pcs = zeros((self.num_align, self.num_spins), uint8)
232
233
234 if self.rdc_flag_sum or self.pcs_flag_sum:
235 for align_index in range(self.num_align):
236
237 if self.rdc_flag_sum:
238 for j in range(self.num_interatom):
239 if isNaN(self.rdc[align_index, j]):
240
241 self.missing_rdc[align_index, j] = 1
242
243
244 self.rdc[align_index, j] = 0.0
245
246
247 self.rdc_error[align_index, j] = 1.0
248
249
250 rdc_weights[align_index, j] = 1.0
251
252
253 if self.rdc_flag_sum:
254 self.rdc_error[align_index, j] = self.rdc_error[align_index, j] / sqrt(rdc_weights[align_index, j])
255
256
257 if self.pcs_flag_sum:
258 for j in range(self.num_spins):
259 if isNaN(self.pcs[align_index, j]):
260
261 self.missing_pcs[align_index, j] = 1
262
263
264 self.pcs[align_index, j] = 0.0
265
266
267 self.pcs_error[align_index, j] = 1.0
268
269
270 pcs_weights[align_index, j] = 1.0
271
272
273 if self.pcs_flag_sum:
274 self.pcs_error[align_index, j] = self.pcs_error[align_index, j] / sqrt(pcs_weights[align_index, j])
275
276
277 if self.pcs_flag_sum:
278
279 self.paramag_unit_vect = zeros(atomic_pos.shape, float64)
280 self.paramag_dist = zeros(self.num_spins, float64)
281 self.pcs_const = zeros(self.num_align, float64)
282 self.r_pivot_atom = zeros((3, self.num_spins), float32)
283 self.r_pivot_atom_rev = zeros((3, self.num_spins), float32)
284 self.r_ln_pivot = zeros((3, self.num_spins), float32)
285 for j in range(self.num_spins):
286 self.r_ln_pivot[:, j] = pivot - self.paramag_centre
287 if self.paramag_centre == None:
288 self.paramag_centre = zeros(3, float32)
289
290
291 for align_index in range(self.num_align):
292 self.pcs_const[align_index] = pcs_constant(self.temp[align_index], self.frq[align_index], 1.0) * 1e30
293
294
295 if self.pcs_flag_sum:
296 self.pcs_theta = zeros((self.num_align, self.num_spins), float64)
297 self.pcs_theta_err = zeros((self.num_align, self.num_spins), float64)
298 self.dpcs_theta = zeros((self.total_num_params, self.num_align, self.num_spins), float64)
299 self.d2pcs_theta = zeros((self.total_num_params, self.total_num_params, self.num_align, self.num_spins), float64)
300
301
302 if self.rdc_flag_sum:
303 self.rdc_theta = zeros((self.num_align, self.num_interatom), float64)
304 self.drdc_theta = zeros((self.total_num_params, self.num_align, self.num_interatom), float64)
305 self.d2rdc_theta = zeros((self.total_num_params, self.total_num_params, self.num_align, self.num_interatom), float64)
306
307
308 if not quad_int and self.pcs_flag_sum and model not in ['rigid']:
309
310 if model == 'pseudo-ellipse':
311 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi', 'sigma'])
312 self.func = self.func_pseudo_ellipse_qrint
313 elif model == 'pseudo-ellipse, torsionless':
314 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi'])
315 self.func = self.func_pseudo_ellipse_torsionless_qrint
316 elif model == 'pseudo-ellipse, free rotor':
317 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi', 'sigma'])
318 self.func = self.func_pseudo_ellipse_free_rotor_qrint
319 elif model == 'iso cone':
320 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi', 'sigma'])
321 self.func = self.func_iso_cone_qrint
322 elif model == 'iso cone, torsionless':
323 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi'])
324 self.func = self.func_iso_cone_torsionless_qrint
325 elif model == 'iso cone, free rotor':
326 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'phi', 'sigma'])
327 self.func = self.func_iso_cone_free_rotor_qrint
328 elif model == 'line':
329 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'sigma'])
330 self.func = self.func_line_qrint
331 elif model == 'line, torsionless':
332 self.create_sobol_data(n=self.num_int_pts, dims=['theta'])
333 self.func = self.func_line_torsionless_qrint
334 elif model == 'line, free rotor':
335 self.create_sobol_data(n=self.num_int_pts, dims=['theta', 'sigma'])
336 self.func = self.func_line_free_rotor_qrint
337 elif model == 'rotor':
338 self.create_sobol_data(n=self.num_int_pts, dims=['sigma'])
339 self.func = self.func_rotor_qrint
340 elif model == 'rigid':
341 self.func = self.func_rigid
342 elif model == 'free rotor':
343 self.create_sobol_data(n=self.num_int_pts, dims=['sigma'])
344 self.func = self.func_free_rotor_qrint
345 elif model == 'double rotor':
346 self.create_sobol_data(n=self.num_int_pts, dims=['sigma', 'sigma2'])
347 self.func = self.func_double_rotor
348
349
350 else:
351 if model == 'pseudo-ellipse':
352 self.func = self.func_pseudo_ellipse
353 elif model == 'pseudo-ellipse, torsionless':
354 self.func = self.func_pseudo_ellipse_torsionless
355 elif model == 'pseudo-ellipse, free rotor':
356 self.func = self.func_pseudo_ellipse_free_rotor
357 elif model == 'iso cone':
358 self.func = self.func_iso_cone
359 elif model == 'iso cone, torsionless':
360 self.func = self.func_iso_cone_torsionless
361 elif model == 'iso cone, free rotor':
362 self.func = self.func_iso_cone_free_rotor
363 elif model == 'line':
364 self.func = self.func_line
365 elif model == 'line, torsionless':
366 self.func = self.func_line_torsionless
367 elif model == 'line, free rotor':
368 self.func = self.func_line_free_rotor
369 elif model == 'rotor':
370 self.func = self.func_rotor
371 elif model == 'rigid':
372 self.func = self.func_rigid
373 elif model == 'free rotor':
374 self.func = self.func_free_rotor
375 elif model == 'double rotor':
376 self.func = self.func_double_rotor
377
378
380 """Set up isotropic cone optimisation against the alignment tensor data."""
381
382
383 if self.full_tensors == None or not len(self.full_tensors):
384 raise RelaxError("The full_tensors argument " + repr(self.full_tensors) + " must be supplied.")
385 if self.full_in_ref_frame == None or not len(self.full_in_ref_frame):
386 raise RelaxError("The full_in_ref_frame argument " + repr(self.full_in_ref_frame) + " must be supplied.")
387
388
389 self.num_tensors = int(len(self.full_tensors) / 5)
390 self.A_3D = zeros((self.num_tensors, 3, 3), float64)
391 self.A_3D_bc = zeros((self.num_tensors, 3, 3), float64)
392 self.A_5D_bc = zeros(self.num_tensors*5, float64)
393
394
395 self.R_eigen = zeros((3, 3), float64)
396 self.R_eigen_2 = zeros((3, 3), float64)
397 self.R_ave = zeros((3, 3), float64)
398 self.Ri_prime = zeros((3, 3), float64)
399 self.tensor_3D = zeros((3, 3), float64)
400
401
402 self.cone_axis = zeros(3, float64)
403 self.z_axis = array([0, 0, 1], float64)
404
405
406 self.rotor_axis = zeros(3, float64)
407 self.rotor_axis_2 = zeros(3, float64)
408
409
410 self.frame_order_2nd = zeros((9, 9), float64)
411
412
413 self.R = zeros((3, 3), float64)
414
415
417 """Target function for the optimisation of the double rotor frame order model.
418
419 This function optimises the model parameters using the RDC and PCS base data. Quasi-random, Sobol' sequence based, numerical integration is used for the PCS.
420
421
422 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi, sigma_max}.
423 @type params: list of float
424 @return: The chi-squared or SSE value.
425 @rtype: float
426 """
427
428
429 if self.scaling_flag:
430 params = dot(params, self.scaling_matrix)
431
432
433 if self.translation_opt and self.pivot_opt:
434 self._param_pivot = params[:3]
435 self._param_pivot2 = params[3:6]
436 self._translation_vector = params[6:9]
437 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, axis_theta_2, axis_phi_2, sigma_max, sigma_max_2 = params[9:]
438 elif self.translation_opt:
439 self._translation_vector = params[:3]
440 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, axis_theta_2, axis_phi_2, sigma_max, sigma_max_2 = params[3:]
441 elif self.pivot_opt:
442 self._param_pivot = params[:3]
443 self._param_pivot2 = params[3:6]
444 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, axis_theta_2, axis_phi_2, sigma_max, sigma_max_2 = params[6:]
445 else:
446 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, axis_theta_2, axis_phi_2, sigma_max, sigma_max_2 = params
447
448
449 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.rotor_axis)
450 spherical_to_cartesian([1.0, axis_theta_2, axis_phi_2], self.rotor_axis_2)
451
452
453 two_vect_to_R(self.z_axis, self.rotor_axis, self.R_eigen)
454 two_vect_to_R(self.z_axis, self.rotor_axis_2, self.R_eigen_2)
455
456
457 R_eigen_full = dot(self.R_eigen_2, self.R_eigen)
458
459
460 Rx2_eigen = kron_prod(R_eigen_full, R_eigen_full)
461
462
463 frame_order_2nd = compile_2nd_matrix_double_rotor(self.frame_order_2nd, Rx2_eigen, sigma_max, sigma_max_2)
464
465
466 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
467
468
469 RT_eigen = transpose(R_eigen_full)
470 RT_ave = transpose(self.R_ave)
471
472
473 if self.pcs_flag:
474 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
475
476
477 chi2_sum = 0.0
478
479
480 for align_index in range(self.num_align):
481
482 if self.rdc_flag[align_index]:
483
484 for j in range(self.num_interatom):
485
486 if not self.missing_rdc[align_index, j]:
487 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
488
489
490 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
491
492
493 if self.pcs_flag_sum:
494
495 pcs_numeric_int_double_rotor(points=self.sobol_angles, sigma_max=sigma_max, sigma_max_2=sigma_max_2, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=R_eigen_full, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
496
497
498 for align_index in range(self.num_align):
499 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
500
501
502 return chi2_sum
503
504
506 """Target function for free rotor model optimisation.
507
508 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
509
510
511 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi}.
512 @type params: list of float
513 @return: The chi-squared or SSE value.
514 @rtype: float
515 """
516
517
518 if self.scaling_flag:
519 params = dot(params, self.scaling_matrix)
520
521
522 if self.translation_opt and self.pivot_opt:
523 self._param_pivot = params[:3]
524 self._translation_vector = params[3:6]
525 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[6:]
526 elif self.translation_opt:
527 self._translation_vector = params[:3]
528 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[3:]
529 elif self.pivot_opt:
530 self._param_pivot = params[:3]
531 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[3:]
532 else:
533 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params
534
535
536 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
537
538
539 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
540
541
542 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
543
544
545 frame_order_2nd = compile_2nd_matrix_free_rotor(self.frame_order_2nd, Rx2_eigen)
546
547
548 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
549
550
551 RT_eigen = transpose(self.R_eigen)
552 RT_ave = transpose(self.R_ave)
553
554
555 if self.pcs_flag:
556 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
557
558
559 chi2_sum = 0.0
560
561
562 for align_index in range(self.num_align):
563
564 if self.rdc_flag[align_index]:
565
566 for j in range(self.num_interatom):
567
568 if not self.missing_rdc[align_index, j]:
569 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
570
571
572 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
573
574
575 if self.pcs_flag[align_index]:
576
577 for j in range(self.num_spins):
578
579 if not self.missing_pcs[align_index, j]:
580
581 if self.full_in_ref_frame[align_index]:
582 r_pivot_atom = self.r_pivot_atom[:, j]
583 else:
584 r_pivot_atom = self.r_pivot_atom_rev[:, j]
585
586
587 self.pcs_theta[align_index, j] = pcs_numeric_int_rotor(sigma_max=pi, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
588
589
590 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
591
592
593 return chi2_sum
594
595
597 """Target function for free rotor model optimisation.
598
599 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
600
601
602 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi}.
603 @type params: list of float
604 @return: The chi-squared or SSE value.
605 @rtype: float
606 """
607
608
609 if self.scaling_flag:
610 params = dot(params, self.scaling_matrix)
611
612
613 if self.translation_opt and self.pivot_opt:
614 self._param_pivot = params[:3]
615 self._translation_vector = params[3:6]
616 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[6:]
617 elif self.translation_opt:
618 self._translation_vector = params[:3]
619 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[3:]
620 elif self.pivot_opt:
621 self._param_pivot = params[:3]
622 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params[3:]
623 else:
624 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params
625
626
627 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
628
629
630 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
631
632
633 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
634
635
636 frame_order_2nd = compile_2nd_matrix_free_rotor(self.frame_order_2nd, Rx2_eigen)
637
638
639 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
640
641
642 RT_eigen = transpose(self.R_eigen)
643 RT_ave = transpose(self.R_ave)
644
645
646 if self.pcs_flag:
647 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
648
649
650 chi2_sum = 0.0
651
652
653 for align_index in range(self.num_align):
654
655 if self.rdc_flag[align_index]:
656
657 for j in range(self.num_interatom):
658
659 if not self.missing_rdc[align_index, j]:
660 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
661
662
663 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
664
665
666 if self.pcs_flag_sum:
667
668 pcs_numeric_int_rotor_qrint(points=self.sobol_angles, sigma_max=pi, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
669
670
671 for align_index in range(self.num_align):
672 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
673
674
675
676 return chi2_sum
677
678
680 """Target function for isotropic cone model optimisation.
681
682 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
683
684
685 @param params: The vector of parameter values {beta, gamma, theta, phi, s1} where the first 2 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, and s1 is the isotropic cone order parameter.
686 @type params: list of float
687 @return: The chi-squared or SSE value.
688 @rtype: float
689 """
690
691
692 if self.scaling_flag:
693 params = dot(params, self.scaling_matrix)
694
695
696 if self.translation_opt and self.pivot_opt:
697 self._param_pivot = params[:3]
698 self._translation_vector = params[3:6]
699 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[6:]
700 elif self.translation_opt:
701 self._translation_vector = params[:3]
702 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[3:]
703 elif self.pivot_opt:
704 self._param_pivot = params[:3]
705 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[3:]
706 else:
707 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params
708
709
710 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
711
712
713 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
714
715
716 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
717
718
719 frame_order_2nd = compile_2nd_matrix_iso_cone(self.frame_order_2nd, Rx2_eigen, cone_theta, sigma_max)
720
721
722 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
723
724
725 RT_eigen = transpose(self.R_eigen)
726 RT_ave = transpose(self.R_ave)
727
728
729 if self.pcs_flag:
730 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
731
732
733 chi2_sum = 0.0
734
735
736 for align_index in range(self.num_align):
737
738 if self.rdc_flag[align_index]:
739
740 for j in range(self.num_interatom):
741
742 if not self.missing_rdc[align_index, j]:
743 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
744
745
746 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
747
748
749 if self.pcs_flag[align_index]:
750
751 for j in range(self.num_spins):
752
753 if not self.missing_pcs[align_index, j]:
754
755 if self.full_in_ref_frame[align_index]:
756 r_pivot_atom = self.r_pivot_atom[:, j]
757 else:
758 r_pivot_atom = self.r_pivot_atom_rev[:, j]
759
760
761 self.pcs_theta[align_index, j] = pcs_numeric_int_iso_cone(theta_max=cone_theta, sigma_max=sigma_max, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
762
763
764 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
765
766
767 return chi2_sum
768
769
771 """Target function for isotropic cone model optimisation.
772
773 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
774
775
776 @param params: The vector of parameter values {alpha, beta, gamma, theta, phi, cone_theta, sigma_max} where the first 3 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, cone_theta is the cone opening half angle, and sigma_max is the torsion angle.
777 @type params: list of float
778 @return: The chi-squared or SSE value.
779 @rtype: float
780 """
781
782
783 if self.scaling_flag:
784 params = dot(params, self.scaling_matrix)
785
786
787 if self.translation_opt and self.pivot_opt:
788 self._param_pivot = params[:3]
789 self._translation_vector = params[3:6]
790 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[6:]
791 elif self.translation_opt:
792 self._translation_vector = params[:3]
793 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[3:]
794 elif self.pivot_opt:
795 self._param_pivot = params[:3]
796 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params[3:]
797 else:
798 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta, sigma_max = params
799
800
801 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
802
803
804 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
805
806
807 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
808
809
810 frame_order_2nd = compile_2nd_matrix_iso_cone(self.frame_order_2nd, Rx2_eigen, cone_theta, sigma_max)
811
812
813 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
814
815
816 RT_eigen = transpose(self.R_eigen)
817 RT_ave = transpose(self.R_ave)
818
819
820 if self.pcs_flag:
821 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
822
823
824 chi2_sum = 0.0
825
826
827 for align_index in range(self.num_align):
828
829 if self.rdc_flag[align_index]:
830
831 for j in range(self.num_interatom):
832
833 if not self.missing_rdc[align_index, j]:
834 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
835
836
837 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
838
839
840 if self.pcs_flag_sum:
841
842 pcs_numeric_int_iso_cone_qrint(points=self.sobol_angles, theta_max=cone_theta, sigma_max=sigma_max, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
843
844
845 for align_index in range(self.num_align):
846 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
847
848
849 return chi2_sum
850
851
853 """Target function for free rotor isotropic cone model optimisation.
854
855 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
856
857
858 @param params: The vector of parameter values {beta, gamma, theta, phi, s1} where the first 2 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, and s1 is the isotropic cone order parameter.
859 @type params: list of float
860 @return: The chi-squared or SSE value.
861 @rtype: float
862 """
863
864
865 if self.scaling_flag:
866 params = dot(params, self.scaling_matrix)
867
868
869 if self.translation_opt and self.pivot_opt:
870 self._param_pivot = params[:3]
871 self._translation_vector = params[3:6]
872 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[6:]
873 elif self.translation_opt:
874 self._translation_vector = params[:3]
875 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[3:]
876 elif self.pivot_opt:
877 self._param_pivot = params[:3]
878 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[3:]
879 else:
880 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params
881
882
883 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
884
885
886 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
887
888
889 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
890
891
892 theta_max = order_parameters.iso_cone_S_to_theta(cone_s1)
893
894
895 frame_order_2nd = compile_2nd_matrix_iso_cone_free_rotor(self.frame_order_2nd, Rx2_eigen, cone_s1)
896
897
898 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
899
900
901 RT_eigen = transpose(self.R_eigen)
902 RT_ave = transpose(self.R_ave)
903
904
905 if self.pcs_flag:
906 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
907
908
909 chi2_sum = 0.0
910
911
912 for align_index in range(self.num_align):
913
914 if self.rdc_flag[align_index]:
915
916 for j in range(self.num_interatom):
917
918 if not self.missing_rdc[align_index, j]:
919 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
920
921
922 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
923
924
925 if self.pcs_flag[align_index]:
926
927 for j in range(self.num_spins):
928
929 if not self.missing_pcs[align_index, j]:
930
931 if self.full_in_ref_frame[align_index]:
932 r_pivot_atom = self.r_pivot_atom[:, j]
933 else:
934 r_pivot_atom = self.r_pivot_atom_rev[:, j]
935
936
937 self.pcs_theta[align_index, j] = pcs_numeric_int_iso_cone(theta_max=theta_max, sigma_max=pi, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
938
939
940 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
941
942
943 return chi2_sum
944
945
947 """Target function for free rotor isotropic cone model optimisation.
948
949 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
950
951
952 @param params: The vector of parameter values {beta, gamma, theta, phi, s1} where the first 2 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, and s1 is the isotropic cone order parameter.
953 @type params: list of float
954 @return: The chi-squared or SSE value.
955 @rtype: float
956 """
957
958
959 if self.scaling_flag:
960 params = dot(params, self.scaling_matrix)
961
962
963 if self.translation_opt and self.pivot_opt:
964 self._param_pivot = params[:3]
965 self._translation_vector = params[3:6]
966 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[6:]
967 elif self.translation_opt:
968 self._translation_vector = params[:3]
969 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[3:]
970 elif self.pivot_opt:
971 self._param_pivot = params[:3]
972 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params[3:]
973 else:
974 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params
975
976
977 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
978
979
980 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
981
982
983 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
984
985
986 theta_max = order_parameters.iso_cone_S_to_theta(cone_s1)
987
988
989 frame_order_2nd = compile_2nd_matrix_iso_cone_free_rotor(self.frame_order_2nd, Rx2_eigen, cone_s1)
990
991
992 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
993
994
995 RT_eigen = transpose(self.R_eigen)
996 RT_ave = transpose(self.R_ave)
997
998
999 if self.pcs_flag:
1000 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1001
1002
1003 chi2_sum = 0.0
1004
1005
1006 for align_index in range(self.num_align):
1007
1008 if self.rdc_flag[align_index]:
1009
1010 for j in range(self.num_interatom):
1011
1012 if not self.missing_rdc[align_index, j]:
1013 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1014
1015
1016 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1017
1018
1019 if self.pcs_flag_sum:
1020
1021 pcs_numeric_int_iso_cone_qrint(points=self.sobol_angles, theta_max=theta_max, sigma_max=pi, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1022
1023
1024 for align_index in range(self.num_align):
1025 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1026
1027
1028 return chi2_sum
1029
1030
1032 """Target function for torsionless isotropic cone model optimisation.
1033
1034 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
1035
1036
1037 @param params: The vector of parameter values {beta, gamma, theta, phi, cone_theta} where the first 2 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, and cone_theta is cone opening angle.
1038 @type params: list of float
1039 @return: The chi-squared or SSE value.
1040 @rtype: float
1041 """
1042
1043
1044 if self.scaling_flag:
1045 params = dot(params, self.scaling_matrix)
1046
1047
1048 if self.translation_opt and self.pivot_opt:
1049 self._param_pivot = params[:3]
1050 self._translation_vector = params[3:6]
1051 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[6:]
1052 elif self.translation_opt:
1053 self._translation_vector = params[:3]
1054 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[3:]
1055 elif self.pivot_opt:
1056 self._param_pivot = params[:3]
1057 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[3:]
1058 else:
1059 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params
1060
1061
1062 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
1063
1064
1065 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
1066
1067
1068 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1069
1070
1071 frame_order_2nd = compile_2nd_matrix_iso_cone_torsionless(self.frame_order_2nd, Rx2_eigen, cone_theta)
1072
1073
1074 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1075
1076
1077 RT_eigen = transpose(self.R_eigen)
1078 RT_ave = transpose(self.R_ave)
1079
1080
1081 if self.pcs_flag:
1082 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1083
1084
1085 chi2_sum = 0.0
1086
1087
1088 for align_index in range(self.num_align):
1089
1090 if self.rdc_flag[align_index]:
1091
1092 for j in range(self.num_interatom):
1093
1094 if not self.missing_rdc[align_index, j]:
1095 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1096
1097
1098 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1099
1100
1101 if self.pcs_flag[align_index]:
1102
1103 for j in range(self.num_spins):
1104
1105 if not self.missing_pcs[align_index, j]:
1106
1107 if self.full_in_ref_frame[align_index]:
1108 r_pivot_atom = self.r_pivot_atom[:, j]
1109 else:
1110 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1111
1112
1113 self.pcs_theta[align_index, j] = pcs_numeric_int_iso_cone_torsionless(theta_max=cone_theta, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
1114
1115
1116 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1117
1118
1119 return chi2_sum
1120
1121
1123 """Target function for torsionless isotropic cone model optimisation.
1124
1125 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
1126
1127
1128 @param params: The vector of parameter values {beta, gamma, theta, phi, cone_theta} where the first 2 are the tensor rotation Euler angles, the next two are the polar and azimuthal angles of the cone axis, and cone_theta is cone opening angle.
1129 @type params: list of float
1130 @return: The chi-squared or SSE value.
1131 @rtype: float
1132 """
1133
1134
1135 if self.scaling_flag:
1136 params = dot(params, self.scaling_matrix)
1137
1138
1139 if self.translation_opt and self.pivot_opt:
1140 self._param_pivot = params[:3]
1141 self._translation_vector = params[3:6]
1142 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[6:]
1143 elif self.translation_opt:
1144 self._translation_vector = params[:3]
1145 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[3:]
1146 elif self.pivot_opt:
1147 self._param_pivot = params[:3]
1148 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params[3:]
1149 else:
1150 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params
1151
1152
1153 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
1154
1155
1156 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
1157
1158
1159 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1160
1161
1162 frame_order_2nd = compile_2nd_matrix_iso_cone_torsionless(self.frame_order_2nd, Rx2_eigen, cone_theta)
1163
1164
1165 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1166
1167
1168 RT_eigen = transpose(self.R_eigen)
1169 RT_ave = transpose(self.R_ave)
1170
1171
1172 if self.pcs_flag:
1173 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1174
1175
1176 chi2_sum = 0.0
1177
1178
1179 for align_index in range(self.num_align):
1180
1181 if self.rdc_flag[align_index]:
1182
1183 for j in range(self.num_interatom):
1184
1185 if not self.missing_rdc[align_index, j]:
1186 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1187
1188
1189 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1190
1191
1192 if self.pcs_flag_sum:
1193
1194 pcs_numeric_int_iso_cone_torsionless_qrint(points=self.sobol_angles, theta_max=cone_theta, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1195
1196
1197 for align_index in range(self.num_align):
1198 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1199
1200
1201 return chi2_sum
1202
1203
1205 """Target function for pseudo-elliptic cone model optimisation.
1206
1207 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
1208
1209
1210 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 3 are the pseudo-elliptic cone geometric parameters.
1211 @type params: list of float
1212 @return: The chi-squared or SSE value.
1213 @rtype: float
1214 """
1215
1216
1217 if self.scaling_flag:
1218 params = dot(params, self.scaling_matrix)
1219
1220
1221 if self.translation_opt and self.pivot_opt:
1222 self._param_pivot = params[:3]
1223 self._translation_vector = params[3:6]
1224 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[6:]
1225 elif self.translation_opt:
1226 self._translation_vector = params[:3]
1227 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[3:]
1228 elif self.pivot_opt:
1229 self._param_pivot = params[:3]
1230 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[3:]
1231 else:
1232 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params
1233
1234
1235 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1236
1237
1238 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1239
1240
1241 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y, cone_sigma_max)
1242
1243
1244 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1245
1246
1247 RT_eigen = transpose(self.R_eigen)
1248 RT_ave = transpose(self.R_ave)
1249
1250
1251 if self.pcs_flag:
1252 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1253
1254
1255 chi2_sum = 0.0
1256
1257
1258 for align_index in range(self.num_align):
1259
1260 if self.rdc_flag[align_index]:
1261
1262 for j in range(self.num_interatom):
1263
1264 if not self.missing_rdc[align_index, j]:
1265 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1266
1267
1268 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1269
1270
1271 if self.pcs_flag[align_index]:
1272
1273 for j in range(self.num_spins):
1274
1275 if not self.missing_pcs[align_index, j]:
1276
1277 if self.full_in_ref_frame[align_index]:
1278 r_pivot_atom = self.r_pivot_atom[:, j]
1279 else:
1280 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1281
1282
1283 self.pcs_theta[align_index, j] = pcs_numeric_int_pseudo_ellipse(theta_x=cone_theta_x, theta_y=cone_theta_y, sigma_max=cone_sigma_max, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
1284
1285
1286 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1287
1288
1289 return chi2_sum
1290
1291
1293 """Target function for pseudo-elliptic cone model optimisation.
1294
1295 This function optimises the model parameters using the RDC and PCS base data. Quasi-random, Sobol' sequence based, numerical integration is used for the PCS.
1296
1297
1298 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 3 are the pseudo-elliptic cone geometric parameters.
1299 @type params: list of float
1300 @return: The chi-squared or SSE value.
1301 @rtype: float
1302 """
1303
1304
1305 if self.scaling_flag:
1306 params = dot(params, self.scaling_matrix)
1307
1308
1309 if self.translation_opt and self.pivot_opt:
1310 self._param_pivot = params[:3]
1311 self._translation_vector = params[3:6]
1312 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[6:]
1313 elif self.translation_opt:
1314 self._translation_vector = params[:3]
1315 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[3:]
1316 elif self.pivot_opt:
1317 self._param_pivot = params[:3]
1318 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params[3:]
1319 else:
1320 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max = params
1321
1322
1323 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1324
1325
1326 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1327
1328
1329 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y, cone_sigma_max)
1330
1331
1332 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1333
1334
1335 RT_eigen = transpose(self.R_eigen)
1336 RT_ave = transpose(self.R_ave)
1337
1338
1339 if self.pcs_flag:
1340 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1341
1342
1343 chi2_sum = 0.0
1344
1345
1346 for align_index in range(self.num_align):
1347
1348 if self.rdc_flag[align_index]:
1349
1350 for j in range(self.num_interatom):
1351
1352 if not self.missing_rdc[align_index, j]:
1353 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1354
1355
1356 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1357
1358
1359 if self.pcs_flag_sum:
1360
1361 pcs_numeric_int_pseudo_ellipse_qrint(points=self.sobol_angles, theta_x=cone_theta_x, theta_y=cone_theta_y, sigma_max=cone_sigma_max, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1362
1363
1364 for align_index in range(self.num_align):
1365 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1366
1367
1368 return chi2_sum
1369
1370
1372 """Target function for free_rotor pseudo-elliptic cone model optimisation.
1373
1374 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
1375
1376
1377 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 2 are the free_rotor pseudo-elliptic cone geometric parameters.
1378 @type params: list of float
1379 @return: The chi-squared or SSE value.
1380 @rtype: float
1381 """
1382
1383
1384 if self.scaling_flag:
1385 params = dot(params, self.scaling_matrix)
1386
1387
1388 if self.translation_opt and self.pivot_opt:
1389 self._param_pivot = params[:3]
1390 self._translation_vector = params[3:6]
1391 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[6:]
1392 elif self.translation_opt:
1393 self._translation_vector = params[:3]
1394 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1395 elif self.pivot_opt:
1396 self._param_pivot = params[:3]
1397 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1398 else:
1399 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
1400
1401
1402 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1403
1404
1405 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1406
1407
1408 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_free_rotor(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y)
1409
1410
1411 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1412
1413
1414 RT_eigen = transpose(self.R_eigen)
1415 RT_ave = transpose(self.R_ave)
1416
1417
1418 if self.pcs_flag:
1419 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1420
1421
1422 chi2_sum = 0.0
1423
1424
1425 for align_index in range(self.num_align):
1426
1427 if self.rdc_flag[align_index]:
1428
1429 for j in range(self.num_interatom):
1430
1431 if not self.missing_rdc[align_index, j]:
1432 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1433
1434
1435 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1436
1437
1438 if self.pcs_flag[align_index]:
1439
1440 for j in range(self.num_spins):
1441
1442 if not self.missing_pcs[align_index, j]:
1443
1444 if self.full_in_ref_frame[align_index]:
1445 r_pivot_atom = self.r_pivot_atom[:, j]
1446 else:
1447 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1448
1449
1450 self.pcs_theta[align_index, j] = pcs_numeric_int_pseudo_ellipse(theta_x=cone_theta_x, theta_y=cone_theta_y, sigma_max=pi, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
1451
1452
1453 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1454
1455
1456 return chi2_sum
1457
1458
1460 """Target function for free_rotor pseudo-elliptic cone model optimisation.
1461
1462 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
1463
1464
1465 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 2 are the free_rotor pseudo-elliptic cone geometric parameters.
1466 @type params: list of float
1467 @return: The chi-squared or SSE value.
1468 @rtype: float
1469 """
1470
1471
1472 if self.scaling_flag:
1473 params = dot(params, self.scaling_matrix)
1474
1475
1476 if self.translation_opt and self.pivot_opt:
1477 self._param_pivot = params[:3]
1478 self._translation_vector = params[3:6]
1479 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[6:]
1480 elif self.translation_opt:
1481 self._translation_vector = params[:3]
1482 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1483 elif self.pivot_opt:
1484 self._param_pivot = params[:3]
1485 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1486 else:
1487 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
1488
1489
1490 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1491
1492
1493 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1494
1495
1496 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_free_rotor(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y)
1497
1498
1499 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1500
1501
1502 RT_eigen = transpose(self.R_eigen)
1503 RT_ave = transpose(self.R_ave)
1504
1505
1506 if self.pcs_flag:
1507 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1508
1509
1510 chi2_sum = 0.0
1511
1512
1513 for align_index in range(self.num_align):
1514
1515 if self.rdc_flag[align_index]:
1516
1517 for j in range(self.num_interatom):
1518
1519 if not self.missing_rdc[align_index, j]:
1520 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1521
1522
1523 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1524
1525
1526 if self.pcs_flag_sum:
1527
1528 pcs_numeric_int_pseudo_ellipse_qrint(points=self.sobol_angles, theta_x=cone_theta_x, theta_y=cone_theta_y, sigma_max=pi, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1529
1530
1531 for align_index in range(self.num_align):
1532 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1533
1534
1535 return chi2_sum
1536
1537
1539 """Target function for torsionless pseudo-elliptic cone model optimisation.
1540
1541 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
1542
1543
1544 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 2 are the torsionless pseudo-elliptic cone geometric parameters.
1545 @type params: list of float
1546 @return: The chi-squared or SSE value.
1547 @rtype: float
1548 """
1549
1550
1551 if self.scaling_flag:
1552 params = dot(params, self.scaling_matrix)
1553
1554
1555 if self.translation_opt and self.pivot_opt:
1556 self._param_pivot = params[:3]
1557 self._translation_vector = params[3:6]
1558 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[6:]
1559 elif self.translation_opt:
1560 self._translation_vector = params[:3]
1561 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1562 elif self.pivot_opt:
1563 self._param_pivot = params[:3]
1564 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1565 else:
1566 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
1567
1568
1569 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1570
1571
1572 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1573
1574
1575 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_torsionless(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y)
1576
1577
1578 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1579
1580
1581 RT_eigen = transpose(self.R_eigen)
1582 RT_ave = transpose(self.R_ave)
1583
1584
1585 if self.pcs_flag:
1586 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1587
1588
1589 chi2_sum = 0.0
1590
1591
1592 for align_index in range(self.num_align):
1593
1594 if self.rdc_flag[align_index]:
1595
1596 for j in range(self.num_interatom):
1597
1598 if not self.missing_rdc[align_index, j]:
1599 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1600
1601
1602 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1603
1604
1605 if self.pcs_flag[align_index]:
1606
1607 for j in range(self.num_spins):
1608
1609 if not self.missing_pcs[align_index, j]:
1610
1611 if self.full_in_ref_frame[align_index]:
1612 r_pivot_atom = self.r_pivot_atom[:, j]
1613 else:
1614 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1615
1616
1617 self.pcs_theta[align_index, j] = pcs_numeric_int_pseudo_ellipse_torsionless(theta_x=cone_theta_x, theta_y=cone_theta_y, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
1618
1619
1620 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1621
1622
1623 return chi2_sum
1624
1625
1627 """Target function for torsionless pseudo-elliptic cone model optimisation.
1628
1629 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Simple numerical integration is used for the PCS.
1630
1631
1632 @param params: The vector of parameter values {alpha, beta, gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y} where the first 3 are the average position rotation Euler angles, the next 3 are the Euler angles defining the eigenframe, and the last 2 are the torsionless pseudo-elliptic cone geometric parameters.
1633 @type params: list of float
1634 @return: The chi-squared or SSE value.
1635 @rtype: float
1636 """
1637
1638
1639 if self.scaling_flag:
1640 params = dot(params, self.scaling_matrix)
1641
1642
1643 if self.translation_opt and self.pivot_opt:
1644 self._param_pivot = params[:3]
1645 self._translation_vector = params[3:6]
1646 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[6:]
1647 elif self.translation_opt:
1648 self._translation_vector = params[:3]
1649 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1650 elif self.pivot_opt:
1651 self._param_pivot = params[:3]
1652 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params[3:]
1653 else:
1654 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
1655
1656
1657 euler_to_R_zyz(eigen_alpha, eigen_beta, eigen_gamma, self.R_eigen)
1658
1659
1660 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1661
1662
1663 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_torsionless(self.frame_order_2nd, Rx2_eigen, cone_theta_x, cone_theta_y)
1664
1665
1666 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1667
1668
1669 RT_eigen = transpose(self.R_eigen)
1670 RT_ave = transpose(self.R_ave)
1671
1672
1673 if self.pcs_flag:
1674 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1675
1676
1677 chi2_sum = 0.0
1678
1679
1680 for align_index in range(self.num_align):
1681
1682 if self.rdc_flag[align_index]:
1683
1684 for j in range(self.num_interatom):
1685
1686 if not self.missing_rdc[align_index, j]:
1687 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1688
1689
1690 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1691
1692
1693 if self.pcs_flag_sum:
1694
1695 pcs_numeric_int_pseudo_ellipse_torsionless_qrint(points=self.sobol_angles, theta_x=cone_theta_x, theta_y=cone_theta_y, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1696
1697
1698 for align_index in range(self.num_align):
1699 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1700
1701
1702 return chi2_sum
1703
1704
1706 """Target function for rigid model optimisation.
1707
1708 This function optimises the isotropic cone model parameters using the RDC and PCS base data.
1709
1710
1711 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma}.
1712 @type params: list of float
1713 @return: The chi-squared or SSE value.
1714 @rtype: float
1715 """
1716
1717
1718 if self.scaling_flag:
1719 params = dot(params, self.scaling_matrix)
1720
1721
1722 if self.translation_opt:
1723 self._translation_vector = params[:3]
1724 ave_pos_alpha, ave_pos_beta, ave_pos_gamma = params[3:6]
1725 else:
1726 ave_pos_alpha, ave_pos_beta, ave_pos_gamma = params
1727
1728
1729 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma)
1730
1731
1732 RT_ave = transpose(self.R_ave)
1733
1734
1735 if self.pcs_flag:
1736 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1737
1738
1739 chi2_sum = 0.0
1740
1741
1742 for align_index in range(self.num_align):
1743
1744 if self.rdc_flag[align_index]:
1745
1746 for j in range(self.num_interatom):
1747
1748 if not self.missing_rdc[align_index, j]:
1749 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1750
1751
1752 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1753
1754
1755 if self.pcs_flag[align_index]:
1756
1757 for j in range(self.num_spins):
1758
1759 if not self.missing_pcs[align_index, j]:
1760
1761 if self.full_in_ref_frame[align_index]:
1762 r_pivot_atom = self.r_pivot_atom[:, j]
1763 else:
1764 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1765
1766
1767 vect = self.r_ln_pivot[:, 0] + r_pivot_atom
1768 length = norm(vect)
1769 self.pcs_theta[align_index, j] = pcs_tensor(self.pcs_const[align_index] / length**5, vect, self.A_3D[align_index])
1770
1771
1772 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1773
1774
1775 return chi2_sum
1776
1777
1779 """Target function for rotor model optimisation.
1780
1781 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Scipy quadratic integration is used for the PCS.
1782
1783
1784 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi, sigma_max}.
1785 @type params: list of float
1786 @return: The chi-squared or SSE value.
1787 @rtype: float
1788 """
1789
1790
1791 if self.scaling_flag:
1792 params = dot(params, self.scaling_matrix)
1793
1794
1795 if self.translation_opt and self.pivot_opt:
1796 self._param_pivot = params[:3]
1797 self._translation_vector = params[3:6]
1798 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, sigma_max = params[6:]
1799 elif self.translation_opt:
1800 self._translation_vector = params[:3]
1801 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, sigma_max = params[3:]
1802 elif self.pivot_opt:
1803 self._param_pivot = params[:3]
1804 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, sigma_max = params[3:]
1805 else:
1806 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, sigma_max = params
1807
1808
1809 spherical_to_cartesian([1.0, axis_theta, axis_phi], self.cone_axis)
1810
1811
1812 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
1813
1814
1815 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1816
1817
1818 frame_order_2nd = compile_2nd_matrix_rotor(self.frame_order_2nd, Rx2_eigen, sigma_max)
1819
1820
1821 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1822
1823
1824 RT_eigen = transpose(self.R_eigen)
1825 RT_ave = transpose(self.R_ave)
1826
1827
1828 if self.pcs_flag:
1829 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1830
1831
1832 chi2_sum = 0.0
1833
1834
1835 for align_index in range(self.num_align):
1836
1837 if self.rdc_flag[align_index]:
1838
1839 for j in range(self.num_interatom):
1840
1841 if not self.missing_rdc[align_index, j]:
1842 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1843
1844
1845 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1846
1847
1848 if self.pcs_flag[align_index]:
1849
1850 for j in range(self.num_spins):
1851
1852 if not self.missing_pcs[align_index, j]:
1853
1854 if self.full_in_ref_frame[align_index]:
1855 r_pivot_atom = self.r_pivot_atom[:, j]
1856 else:
1857 r_pivot_atom = self.r_pivot_atom_rev[:, j]
1858
1859
1860 self.pcs_theta[align_index, j] = pcs_numeric_int_rotor(sigma_max=sigma_max, c=self.pcs_const[align_index], r_pivot_atom=r_pivot_atom, r_ln_pivot=self.r_ln_pivot[:, 0], A=self.A_3D[align_index], R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime)
1861
1862
1863 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1864
1865
1866 return chi2_sum
1867
1868
1870 """Target function for rotor model optimisation.
1871
1872 This function optimises the isotropic cone model parameters using the RDC and PCS base data. Quasi-random, Sobol' sequence based, numerical integration is used for the PCS.
1873
1874
1875 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi, sigma_max}.
1876 @type params: list of float
1877 @return: The chi-squared or SSE value.
1878 @rtype: float
1879 """
1880
1881
1882 if self.scaling_flag:
1883 params = dot(params, self.scaling_matrix)
1884
1885
1886 if self.translation_opt and self.pivot_opt:
1887 self._param_pivot = params[:3]
1888 self._translation_vector = params[3:6]
1889 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_alpha, sigma_max = params[6:]
1890 elif self.translation_opt:
1891 self._translation_vector = params[:3]
1892 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_alpha, sigma_max = params[3:]
1893 elif self.pivot_opt:
1894 self._param_pivot = params[:3]
1895 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_alpha, sigma_max = params[3:]
1896 else:
1897 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_alpha, sigma_max = params
1898
1899
1900 self.cone_axis = create_rotor_axis_alpha(alpha=axis_alpha, pivot=array(self._param_pivot, float64), point=self.com)
1901
1902
1903 two_vect_to_R(self.z_axis, self.cone_axis, self.R_eigen)
1904
1905
1906 Rx2_eigen = kron_prod(self.R_eigen, self.R_eigen)
1907
1908
1909 frame_order_2nd = compile_2nd_matrix_rotor(self.frame_order_2nd, Rx2_eigen, sigma_max)
1910
1911
1912 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
1913
1914
1915 RT_eigen = transpose(self.R_eigen)
1916 RT_ave = transpose(self.R_ave)
1917
1918
1919 if self.pcs_flag:
1920 self.calc_vectors(self._param_pivot, self.R_ave, RT_ave)
1921
1922
1923 chi2_sum = 0.0
1924
1925
1926 for align_index in range(self.num_align):
1927
1928 if self.rdc_flag[align_index]:
1929
1930 for j in range(self.num_interatom):
1931
1932 if not self.missing_rdc[align_index, j]:
1933 self.rdc_theta[align_index, j] = rdc_tensor(self.dip_const[j], self.rdc_vect[j], self.A_3D_bc[align_index])
1934
1935
1936 chi2_sum = chi2_sum + chi2(self.rdc[align_index], self.rdc_theta[align_index], self.rdc_error[align_index])
1937
1938
1939 if self.pcs_flag_sum:
1940
1941 pcs_numeric_int_rotor_qrint(points=self.sobol_angles, sigma_max=sigma_max, c=self.pcs_const, full_in_ref_frame=self.full_in_ref_frame, r_pivot_atom=self.r_pivot_atom, r_pivot_atom_rev=self.r_pivot_atom_rev, r_ln_pivot=self.r_ln_pivot, A=self.A_3D, R_eigen=self.R_eigen, RT_eigen=RT_eigen, Ri_prime=self.Ri_prime, pcs_theta=self.pcs_theta, pcs_theta_err=self.pcs_theta_err, missing_pcs=self.missing_pcs, error_flag=False)
1942
1943
1944 for align_index in range(self.num_align):
1945 chi2_sum = chi2_sum + chi2(self.pcs[align_index], self.pcs_theta[align_index], self.pcs_error[align_index])
1946
1947
1948 return chi2_sum
1949
1950
1951 - def calc_vectors(self, pivot=None, R_ave=None, RT_ave=None):
1952 """Calculate the pivot to atom and lanthanide to pivot vectors for the target functions.
1953
1954 @keyword pivot: The pivot point.
1955 @type pivot: numpy rank-1, 3D array
1956 @keyword R_ave: The rotation matrix for rotating from the reference frame to the average position.
1957 @type R_ave: numpy rank-2, 3D array
1958 @keyword RT_ave: The transpose of R_ave.
1959 @type RT_ave: numpy rank-2, 3D array
1960 """
1961
1962
1963 if self.ave_pos_piv_sync:
1964 ave_pos_pivot = self._param_pivot
1965 else:
1966 ave_pos_pivot = self.ave_pos_pivot
1967
1968
1969 for j in range(self.num_spins):
1970
1971 if self.pivot_opt:
1972 self.r_ln_pivot[:, j] = pivot - self.paramag_centre
1973
1974
1975 self.r_pivot_atom[:, j] = dot(R_ave, self.atomic_pos[j] - ave_pos_pivot) + ave_pos_pivot
1976 self.r_pivot_atom[:, j] += self._translation_vector
1977 self.r_pivot_atom[:, j] -= pivot
1978 self.r_pivot_atom_rev[:, j] = dot(RT_ave, self.atomic_pos[j] - ave_pos_pivot) + ave_pos_pivot
1979 self.r_pivot_atom_rev[:, j] += self._translation_vector
1980 self.r_pivot_atom_rev[:, j] -= pivot
1981
1982
1984 """Create the Sobol' quasi-random data for numerical integration.
1985
1986 This uses the external sobol_lib module to create the data. The algorithm is that modified by Antonov and Saleev.
1987
1988
1989 @keyword n: The number of points to generate.
1990 @type n: int
1991 @keyword dims: The list of parameters.
1992 @type dims: list of str
1993 """
1994
1995
1996 m = len(dims)
1997
1998
1999 self.sobol_angles = zeros((n, m), float32)
2000
2001
2002 for i in range(n):
2003
2004 point, seed = i4_sobol(m, i)
2005
2006
2007 for j in range(m):
2008
2009 if dims[j] in ['theta']:
2010 self.sobol_angles[i, j] = acos(2.0*point[j] - 1.0)
2011
2012
2013 if dims[j] in ['phi']:
2014 self.sobol_angles[i, j] = 2.0 * pi * point[j]
2015
2016
2017 if dims[j] in ['sigma', 'sigma2']:
2018 self.sobol_angles[i, j] = 2.0 * pi * (point[j] - 0.5)
2019
2020
2021 - def reduce_and_rot(self, ave_pos_alpha=None, ave_pos_beta=None, ave_pos_gamma=None, daeg=None):
2022 """Reduce and rotate the alignments tensors using the frame order matrix and Euler angles.
2023
2024 @keyword ave_pos_alpha: The alpha Euler angle describing the average domain position, the tensor rotation.
2025 @type ave_pos_alpha: float
2026 @keyword ave_pos_beta: The beta Euler angle describing the average domain position, the tensor rotation.
2027 @type ave_pos_beta: float
2028 @keyword ave_pos_gamma: The gamma Euler angle describing the average domain position, the tensor rotation.
2029 @type ave_pos_gamma: float
2030 @keyword daeg: The 2nd degree frame order matrix.
2031 @type daeg: rank-2, 9D array
2032 """
2033
2034
2035 euler_to_R_zyz(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, self.R_ave)
2036
2037
2038 for align_index in range(self.num_tensors):
2039
2040 index1 = align_index*5
2041 index2 = align_index*5+5
2042
2043
2044 if daeg != None:
2045
2046 reduce_alignment_tensor(daeg, self.full_tensors[index1:index2], self.A_5D_bc[index1:index2])
2047
2048
2049 to_tensor(self.tensor_3D, self.A_5D_bc[index1:index2])
2050
2051
2052 else:
2053
2054 to_tensor(self.tensor_3D, self.full_tensors[index1:index2])
2055
2056
2057 if self.full_in_ref_frame[align_index]:
2058 self.A_3D_bc[align_index] = dot(transpose(self.R_ave), dot(self.tensor_3D, self.R_ave))
2059
2060
2061 else:
2062 self.A_3D_bc[align_index] = dot(self.R_ave, dot(self.tensor_3D, transpose(self.R_ave)))
2063
2064
2065 to_5D(self.A_5D_bc[index1:index2], self.A_3D_bc[align_index])
2066