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 numpy import array, dot, float64, ones, transpose, zeros
28
29
30 from generic_fns.frame_order import print_frame_order_2nd_degree
31 from maths_fns.alignment_tensor import to_5D, to_tensor
32 from maths_fns.chi2 import chi2
33 from maths_fns.frame_order_matrix_ops import compile_2nd_matrix_free_rotor, compile_2nd_matrix_iso_cone, compile_2nd_matrix_iso_cone_free_rotor, compile_2nd_matrix_iso_cone_torsionless, compile_2nd_matrix_pseudo_ellipse, compile_2nd_matrix_pseudo_ellipse_free_rotor, compile_2nd_matrix_pseudo_ellipse_torsionless, compile_2nd_matrix_rotor, reduce_alignment_tensor
34 from maths_fns.rotation_matrix import euler_to_R_zyz as euler_to_R
35 from relax_errors import RelaxError
36
37
39 """Class containing the target function of the optimisation of Frame Order matrix components."""
40
41 - def __init__(self, model=None, init_params=None, full_tensors=None, red_tensors=None, red_errors=None, full_in_ref_frame=None, frame_order_2nd=None):
42 """Set up the target functions for the Frame Order theories.
43
44 @keyword model: The name of the Frame Order model.
45 @type model: str
46 @keyword init_params: The initial parameter values.
47 @type init_params: numpy float64 array
48 @keyword full_tensors: An array of the {Sxx, Syy, Sxy, Sxz, Syz} values for all full alignment tensors. The format is [Sxx1, Syy1, Sxy1, Sxz1, Syz1, Sxx2, Syy2, Sxy2, Sxz2, Syz2, ..., Sxxn, Syyn, Sxyn, Sxzn, Syzn].
49 @type full_tensors: numpy nx5D, rank-1 float64 array
50 @keyword red_tensors: An array of the {Sxx, Syy, Sxy, Sxz, Syz} values for all reduced tensors. The array format is the same as for full_tensors.
51 @type red_tensors: numpy nx5D, rank-1 float64 array
52 @keyword red_errors: An array of the {Sxx, Syy, Sxy, Sxz, Syz} errors for all reduced tensors. The array format is the same as for full_tensors.
53 @type red_errors: numpy nx5D, rank-1 float64 array
54 @keyword full_in_ref_frame: An array of flags specifying if the tensor in the reference frame is the full or reduced tensor.
55 @type full_in_ref_frame: numpy rank-1 array
56 @keyword frame_order_2nd: The numerical values of the 2nd degree Frame Order matrix. If supplied, the target functions will optimise directly to these values.
57 @type frame_order_2nd: None or numpy 9D, rank-2 array
58 """
59
60
61 if not model:
62 raise RelaxError("The type of Frame Order model must be specified.")
63
64
65 self.params = deepcopy(init_params)
66
67
68 self.model = model
69 self.full_tensors = full_tensors
70 self.red_tensors = red_tensors
71 self.red_errors = red_errors
72 self.full_in_ref_frame = full_in_ref_frame
73
74
75 if full_tensors != None and frame_order_2nd != None:
76 raise RelaxError("Tensors and Frame Order matrices cannot be supplied together.")
77 if full_tensors == None and frame_order_2nd == None:
78 raise RelaxError("The arguments have been incorrectly supplied, cannot determine the optimisation mode.")
79
80
81 if full_tensors != None:
82 self.__init_tensors()
83
84
85 if model == 'iso cone, free rotor' and frame_order_2nd != None:
86 self.__init_iso_cone_elements(frame_order_2nd)
87
88
89 if model == 'pseudo-ellipse':
90 self.func = self.func_pseudo_ellipse
91 elif model == 'pseudo-ellipse, torsionless':
92 self.func = self.func_pseudo_ellipse_torsionless
93 elif model == 'pseudo-ellipse, free rotor':
94 self.func = self.func_pseudo_ellipse_free_rotor
95 elif model == 'iso cone':
96 self.func = self.func_iso_cone
97 elif model == 'iso cone, torsionless':
98 self.func = self.func_iso_cone_torsionless
99 elif model == 'iso cone, free rotor':
100 self.func = self.func_iso_cone_free_rotor
101 elif model == 'line':
102 self.func = self.func_line
103 elif model == 'line, torsionless':
104 self.func = self.func_line_torsionless
105 elif model == 'line, free rotor':
106 self.func = self.func_line_free_rotor
107 elif model == 'rotor':
108 self.func = self.func_rotor
109 elif model == 'rigid':
110 self.func = self.func_rigid
111 elif model == 'free rotor':
112 self.func = self.func_free_rotor
113
114
116 """Set up isotropic cone optimisation against the alignment tensor data."""
117
118
119 if self.full_tensors == None or not len(self.full_tensors):
120 raise RelaxError("The full_tensors argument " + repr(self.full_tensors) + " must be supplied.")
121 if self.red_tensors == None or not len(self.red_tensors):
122 raise RelaxError("The red_tensors argument " + repr(self.red_tensors) + " must be supplied.")
123 if self.red_errors == None or not len(self.red_errors):
124 raise RelaxError("The red_errors argument " + repr(self.red_errors) + " must be supplied.")
125 if self.full_in_ref_frame == None or not len(self.full_in_ref_frame):
126 raise RelaxError("The full_in_ref_frame argument " + repr(self.full_in_ref_frame) + " must be supplied.")
127
128
129 self.num_tensors = int(len(self.full_tensors) / 5)
130 self.red_tensors_bc = zeros(self.num_tensors*5, float64)
131
132
133 self.rot = zeros((3, 3), float64)
134 self.tensor_3D = zeros((3, 3), float64)
135
136
137 self.cone_axis = zeros(3, float64)
138 self.z_axis = array([0, 0, 1], float64)
139
140
141 self.frame_order_2nd = zeros((9, 9), float64)
142
143
145 """Set up isotropic cone optimisation against the 2nd degree Frame Order matrix elements.
146
147 @keyword frame_order_2nd: The numerical values of the 2nd degree Frame Order matrix. If supplied, the target functions will optimise directly to these values.
148 @type frame_order_2nd: numpy 9D, rank-2 array
149 """
150
151
152 self.data = frame_order_2nd
153
154
155 self.errors = ones((9, 9), float64)
156
157
158 self.cone_axis = zeros(3, float64)
159 self.z_axis = array([0, 0, 1], float64)
160
161
162 self.rot = zeros((3, 3), float64)
163
164
165 self.frame_order_2nd = zeros((9, 9), float64)
166
167
168 self.func = self.func_iso_cone_elements
169
170
172 """Target function for free rotor model optimisation.
173
174 This function optimises against alignment tensors. The Euler angles for the tensor rotation are the first 3 parameters optimised in this model, followed by the polar and azimuthal angles of the cone axis.
175
176 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi}.
177 @type params: list of float
178 @return: The chi-squared or SSE value.
179 @rtype: float
180 """
181
182
183 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi = params
184
185
186 frame_order_2nd = compile_2nd_matrix_free_rotor(self.frame_order_2nd, self.rot, self.z_axis, self.cone_axis, axis_theta, axis_phi)
187
188
189 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
190
191
192 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
193
194
196 """Target function for isotropic cone model optimisation using the Frame Order matrix.
197
198 This function optimises by directly matching the elements of the 2nd degree Frame Order
199 super matrix. The cone axis spherical angles theta and phi and the cone angle theta are the
200 3 parameters optimised in this model.
201
202 @param params: The vector of parameter values {theta, phi, theta_cone} where the first two are the polar and azimuthal angles of the cone axis theta_cone is the isotropic cone angle.
203 @type params: list of float
204 @return: The chi-squared or SSE value.
205 @rtype: float
206 """
207
208
209 theta, phi, theta_cone = params
210
211
212 self.frame_order_2nd = compile_2nd_matrix_iso_cone_free_rotor(self.frame_order_2nd, self.rot, self.z_axis, self.cone_axis, theta, phi, theta_cone)
213
214
215 self.frame_order_2nd = self.frame_order_2nd.copy()
216
217
218 self.data.shape = (81,)
219 self.frame_order_2nd.shape = (81,)
220 self.errors.shape = (81,)
221
222
223 val = chi2(self.data, self.frame_order_2nd, self.errors)
224
225
226 self.data.shape = (9, 9)
227 self.frame_order_2nd.shape = (9, 9)
228 self.errors.shape = (9, 9)
229
230
231 return val
232
233
235 """Target function for isotropic cone model optimisation.
236
237 This function optimises against alignment tensors.
238
239 @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.
240 @type params: list of float
241 @return: The chi-squared or SSE value.
242 @rtype: float
243 """
244
245
246 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta, sigma_max = params
247
248
249 frame_order_2nd = compile_2nd_matrix_iso_cone(self.frame_order_2nd, self.rot, eigen_alpha, eigen_beta, eigen_gamma, cone_theta, sigma_max)
250
251
252 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
253
254
255 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
256
257
259 """Target function for free rotor isotropic cone model optimisation.
260
261 This function optimises against alignment tensors.
262
263 @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.
264 @type params: list of float
265 @return: The chi-squared or SSE value.
266 @rtype: float
267 """
268
269
270 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_s1 = params
271
272
273 frame_order_2nd = compile_2nd_matrix_iso_cone_free_rotor(self.frame_order_2nd, self.rot, self.z_axis, self.cone_axis, axis_theta, axis_phi, cone_s1)
274
275
276 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
277
278
279 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
280
281
283 """Target function for torsionless isotropic cone model optimisation.
284
285 This function optimises against alignment tensors.
286
287 @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.
288 @type params: list of float
289 @return: The chi-squared or SSE value.
290 @rtype: float
291 """
292
293
294 ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, cone_theta = params
295
296
297 frame_order_2nd = compile_2nd_matrix_iso_cone_torsionless(self.frame_order_2nd, self.rot, self.z_axis, self.cone_axis, axis_theta, axis_phi, cone_theta)
298
299
300 self.reduce_and_rot(0.0, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
301
302
303 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
304
305
307 """Target function for pseudo-elliptic cone model optimisation.
308
309 @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.
310 @type params: list of float
311 @return: The chi-squared or SSE value.
312 @rtype: float
313 """
314
315
316 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
317
318
319 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse(self.frame_order_2nd, self.rot, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, cone_sigma_max)
320
321
322 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
323
324
325 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
326
327
329 """Target function for free_rotor pseudo-elliptic cone model optimisation.
330
331 @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.
332 @type params: list of float
333 @return: The chi-squared or SSE value.
334 @rtype: float
335 """
336
337
338 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
339
340
341 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_free_rotor(self.frame_order_2nd, self.rot, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y)
342
343
344 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
345
346
347 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
348
349
351 """Target function for torsionless pseudo-elliptic cone model optimisation.
352
353 @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.
354 @type params: list of float
355 @return: The chi-squared or SSE value.
356 @rtype: float
357 """
358
359
360 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y = params
361
362
363 frame_order_2nd = compile_2nd_matrix_pseudo_ellipse_torsionless(self.frame_order_2nd, self.rot, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y)
364
365
366 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
367
368
369 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
370
371
373 """Target function for rigid model optimisation.
374
375 This function optimises against alignment tensors. The Euler angles for the tensor rotation are the 3 parameters optimised in this model.
376
377 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma}.
378 @type params: list of float
379 @return: The chi-squared or SSE value.
380 @rtype: float
381 """
382
383
384 ave_pos_alpha, ave_pos_beta, ave_pos_gamma = params
385
386
387 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma)
388
389
390 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
391
392
394 """Target function for rotor model optimisation.
395
396 This function optimises against alignment tensors. The Euler angles for the tensor rotation are the first 3 parameters optimised in this model, followed by the polar and azimuthal angles of the cone axis and the torsion angle restriction.
397
398 @param params: The vector of parameter values. These are the tensor rotation angles {alpha, beta, gamma, theta, phi, sigma_max}.
399 @type params: list of float
400 @return: The chi-squared or SSE value.
401 @rtype: float
402 """
403
404
405 ave_pos_alpha, ave_pos_beta, ave_pos_gamma, axis_theta, axis_phi, sigma_max = params
406
407
408 frame_order_2nd = compile_2nd_matrix_rotor(self.frame_order_2nd, self.rot, self.z_axis, self.cone_axis, axis_theta, axis_phi, sigma_max)
409
410
411 self.reduce_and_rot(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, frame_order_2nd)
412
413
414 return chi2(self.red_tensors, self.red_tensors_bc, self.red_errors)
415
416
417 - def reduce_and_rot(self, ave_pos_alpha=None, ave_pos_beta=None, ave_pos_gamma=None, daeg=None):
418 """Reduce and rotate the alignments tensors using the frame order matrix and Euler angles.
419
420 @keyword ave_pos_alpha: The alpha Euler angle describing the average domain position, the tensor rotation.
421 @type ave_pos_alpha: float
422 @keyword ave_pos_beta: The beta Euler angle describing the average domain position, the tensor rotation.
423 @type ave_pos_beta: float
424 @keyword ave_pos_gamma: The gamma Euler angle describing the average domain position, the tensor rotation.
425 @type ave_pos_gamma: float
426 @keyword daeg: The 2nd degree frame order matrix.
427 @type daeg: rank-2, 9D array
428 """
429
430
431 euler_to_R(ave_pos_alpha, ave_pos_beta, ave_pos_gamma, self.rot)
432
433
434 for i in range(self.num_tensors):
435
436 index1 = i*5
437 index2 = i*5+5
438
439
440 if daeg != None:
441
442 reduce_alignment_tensor(daeg, self.full_tensors[index1:index2], self.red_tensors_bc[index1:index2])
443
444
445 to_tensor(self.tensor_3D, self.red_tensors_bc[index1:index2])
446
447
448 else:
449
450 to_tensor(self.tensor_3D, self.full_tensors[index1:index2])
451
452
453 if self.full_in_ref_frame[i]:
454 tensor_3D = dot(self.rot, dot(self.tensor_3D, transpose(self.rot)))
455
456
457 else:
458 tensor_3D = dot(transpose(self.rot), dot(self.tensor_3D, self.rot))
459
460
461 to_5D(self.red_tensors_bc[index1:index2], tensor_3D)
462