1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 from re import search
25 from math import cos, sin
26 from numpy import array, dot, eye, float64, identity, transpose, zeros
27 from numpy.linalg import det, eig, eigvals
28 from types import ListType
29
30
31 from data_classes import Element
32 from float import nan
33 from maths_fns.rotation_matrix import R_to_euler_zyz
34 from relax_errors import RelaxError
35 from relax_xml import fill_object_contents, xml_to_object
36
37
38
39 -def calc_A(Axx, Ayy, Azz, Axy, Axz, Ayz):
40 """Function for calculating the alignment tensor (in the structural frame).
41
42 @param Axx: The Axx tensor element.
43 @type Axx: float
44 @param Ayy: The Ayy tensor element.
45 @type Ayy: float
46 @param Azz: The Azz tensor element.
47 @type Azz: float
48 @param Axy: The Axy tensor element.
49 @type Axy: float
50 @param Axz: The Axz tensor element.
51 @type Axz: float
52 @param Ayz: The Ayz tensor element.
53 @type Ayz: float
54 @return: The alignment tensor (within the structural frame).
55 @rtype: 3x3 numpy float64 array
56 """
57
58
59 tensor = zeros((3, 3), float64)
60
61
62 tensor[0, 0] = Axx
63 tensor[1, 1] = Ayy
64 tensor[2, 2] = Azz
65
66
67 tensor[0, 1] = tensor[1, 0] = Axy
68 tensor[0, 2] = tensor[2, 0] = Axz
69 tensor[1, 2] = tensor[2, 1] = Ayz
70
71
72 return tensor
73
74
76 """Function for calculating the alignment tensor in the 5D vector notation.
77
78 @param Axx: The Axx tensor element.
79 @type Axx: float
80 @param Ayy: The Ayy tensor element.
81 @type Ayy: float
82 @param Azz: The Azz tensor element.
83 @type Azz: float
84 @param Axy: The Axy tensor element.
85 @type Axy: float
86 @param Axz: The Axz tensor element.
87 @type Axz: float
88 @param Ayz: The Ayz tensor element.
89 @type Ayz: float
90 @return: The alignment 5D tensor (within the structural frame).
91 @rtype: numpy rank-1 5D tensor
92 """
93
94
95 tensor = zeros(5, float64)
96
97
98 tensor[0] = Axx
99 tensor[1] = Ayy
100 tensor[2] = Axy
101 tensor[3] = Axz
102 tensor[4] = Ayz
103
104
105 return tensor
106
107
109 """Calculate the diagonalised alignment tensor.
110
111 The diagonalised alignment tensor is defined as::
112
113 | Axx' 0 0 |
114 tensor = | 0 Ayy' 0 |.
115 | 0 0 Azz'|
116
117 The diagonalised alignment tensor is calculated by eigenvalue decomposition.
118
119
120 @param A: The full alignment tensor.
121 @type A: numpy array ((3, 3), float64)
122 @return: The diagonalised alignment tensor.
123 @rtype: numpy array ((3, 3), float64)
124 """
125
126
127 vals = eigvals(A)
128
129
130 abs_vals = abs(vals).tolist()
131 Axx_index = abs_vals.index(min(abs_vals))
132 Azz_index = abs_vals.index(max(abs_vals))
133 last_index = range(3)
134 last_index.pop(max(Axx_index, Azz_index))
135 last_index.pop(min(Axx_index, Azz_index))
136 Ayy_index = last_index[0]
137
138
139 tensor_diag = zeros((3, 3), float64)
140
141
142 tensor_diag[0, 0] = vals[Axx_index]
143 tensor_diag[1, 1] = vals[Ayy_index]
144 tensor_diag[2, 2] = vals[Azz_index]
145
146
147 return tensor_diag
148
149
151 """Calculate the anisotropic parameter Aa.
152
153 This is given by::
154
155 Aa = 3/2Azz = Szz,
156
157 where Azz and Szz are the eigenvalues.
158
159
160 @param A_diag: The full alignment tensor, diagonalised.
161 @type A_diag: numpy array ((3, 3), float64)
162 @return: The Aa parameter
163 @rtype: float
164 """
165
166
167 return 1.5 * A_diag[2, 2]
168
169
171 """Calculate the rhombic parameter Ar.
172
173 This is given by::
174
175 Ar = Axx - Ayy,
176
177 where Axx and Ayy are the eigenvalues.
178
179
180 @param A_diag: The full alignment tensor, diagonalised.
181 @type A_diag: numpy array ((3, 3), float64)
182 @return: The Ar parameter
183 @rtype: float
184 """
185
186
187 return A_diag[0, 0] - A_diag[1, 1]
188
189
191 """Function for calculating the Axx-yy value.
192
193 The equation for calculating the parameter is::
194
195 Axx-yy = Axx - Ayy.
196
197 @param Axx: The Axx component of the alignment tensor.
198 @type Axx: float
199 @param Ayy: The Ayy component of the alignment tensor.
200 @type Ayy: float
201 @return: The Axx-yy component of the alignment tensor.
202 @rtype: float
203 """
204
205
206 return Axx - Ayy
207
208
210 """Function for calculating the Azz value.
211
212 The equation for calculating the parameter is::
213
214 Azz = - Axx - Ayy.
215
216 @param Axx: The Axx component of the alignment tensor.
217 @type Axx: float
218 @param Ayy: The Ayy component of the alignment tensor.
219 @type Ayy: float
220 @return: The Azz component of the alignment tensor.
221 @rtype: float
222 """
223
224
225 return - Axx - Ayy
226
227
229 """Calculate the eigenvalues and eigenvectors of the alignment tensor (A).
230
231 @param A: The full alignment tensor.
232 @type A: numpy array ((3, 3), float64)
233 @return: The eigensystem.
234 @rtype: tuple of numpy array (float64)
235 """
236
237
238 vals = eigvals(A)
239
240
241 abs_vals = abs(vals).tolist()
242 x_index = abs_vals.index(min(abs_vals))
243 z_index = abs_vals.index(max(abs_vals))
244 last_index = range(3)
245 last_index.pop(max(x_index, z_index))
246 last_index.pop(min(x_index, z_index))
247 y_index = last_index[0]
248
249
250 return [vals[x_index], vals[y_index], vals[z_index]]
251
252
254 """Calculate the asymmetry parameter eta.
255
256 This is given by::
257
258 eta = (Axx - Ayy) / Azz
259
260 where Aii are the eigenvalues.
261
262
263 @param A_diag: The full alignment tensor, diagonalised.
264 @type A_diag: numpy array ((3, 3), float64)
265 @return: The eta parameter
266 @rtype: float
267 """
268
269
270 if A_diag[2, 2] == 0:
271 return nan
272
273
274 return (A_diag[0, 0] - A_diag[1, 1]) / A_diag[2, 2]
275
276
278 """Calculate the zyz notation Euler angles.
279
280 @param rotation: The rotation matrix.
281 @type rotation: numpy 3D, rank-2 array
282 @return: The Euler angles alpha, beta, and gamma in zyz notation.
283 @rtype: tuple of float
284 """
285
286 return R_to_euler_zyz(rotation)
287
288
289 -def calc_S(Sxx, Syy, Szz, Sxy, Sxz, Syz):
290 """Function for calculating the alignment tensor (in the structural frame).
291
292 @param Sxx: The Sxx tensor element.
293 @type Sxx: float
294 @param Syy: The Syy tensor element.
295 @type Syy: float
296 @param Szz: The Szz tensor element.
297 @type Szz: float
298 @param Sxy: The Sxy tensor element.
299 @type Sxy: float
300 @param Sxz: The Sxz tensor element.
301 @type Sxz: float
302 @param Syz: The Syz tensor element.
303 @type Syz: float
304 @return: The alignment tensor (within the structural frame).
305 @rtype: 3x3 numpy float64 array
306 """
307
308
309 tensor = zeros((3, 3), float64)
310
311
312 tensor[0, 0] = Sxx
313 tensor[1, 1] = Syy
314 tensor[2, 2] = Szz
315
316
317 tensor[0, 1] = tensor[1, 0] = Sxy
318 tensor[0, 2] = tensor[2, 0] = Sxz
319 tensor[1, 2] = tensor[2, 1] = Syz
320
321
322 return tensor
323
324
326 """Function for calculating the alignment tensor in the 5D vector notation.
327
328 @param Sxx: The Sxx tensor element.
329 @type Sxx: float
330 @param Syy: The Syy tensor element.
331 @type Syy: float
332 @param Szz: The Szz tensor element.
333 @type Szz: float
334 @param Sxy: The Sxy tensor element.
335 @type Sxy: float
336 @param Sxz: The Sxz tensor element.
337 @type Sxz: float
338 @param Syz: The Syz tensor element.
339 @type Syz: float
340 @return: The alignment 5D tensor (within the structural frame).
341 @rtype: numpy rank-1 5D tensor
342 """
343
344
345 tensor = zeros(5, float64)
346
347
348 tensor[0] = Sxx
349 tensor[1] = Syy
350 tensor[2] = Sxy
351 tensor[3] = Sxz
352 tensor[4] = Syz
353
354
355 return tensor
356
357
359 """Calculate the diagonalised alignment tensor.
360
361 The diagonalised alignment tensor is defined as::
362
363 | Sxx' 0 0 |
364 tensor = | 0 Syy' 0 |.
365 | 0 0 Szz'|
366
367 The diagonalised alignment tensor is calculated by eigenvalue decomposition.
368
369
370 @param tensor: The full alignment tensor in its eigenframe.
371 @type tensor: numpy array ((3, 3), float64)
372 @return: The diagonalised alignment tensor.
373 @rtype: numpy array ((3, 3), float64)
374 """
375
376
377 vals = eigvals(tensor)
378
379
380 abs_vals = abs(vals).tolist()
381 Sxx_index = abs_vals.index(min(abs_vals))
382 Szz_index = abs_vals.index(max(abs_vals))
383 last_index = range(3)
384 last_index.pop(max(Sxx_index, Szz_index))
385 last_index.pop(min(Sxx_index, Szz_index))
386 Syy_index = last_index[0]
387
388
389 tensor_diag = zeros((3, 3), float64)
390
391
392 tensor_diag[0, 0] = vals[Sxx_index]
393 tensor_diag[1, 1] = vals[Syy_index]
394 tensor_diag[2, 2] = vals[Szz_index]
395
396
397 return tensor_diag
398
399
401 """Function for calculating the Axx value.
402
403 The equation for calculating the parameter is::
404
405 Sxx = 3/2 Axx.
406
407 @param Axx: The Axx component of the alignment tensor.
408 @type Axx: float
409 @rtype: float
410 """
411
412
413 return 3.0/2.0 * Axx
414
415
417 """Function for calculating the Sxx-yy value.
418
419 The equation for calculating the parameter is::
420
421 Sxx-yy = Sxx - Syy.
422
423 @param Sxx: The Sxx component of the Saupe order matrix.
424 @type Sxx: float
425 @param Syy: The Syy component of the Saupe order matrix.
426 @type Syy: float
427 @return: The Sxx-yy component of the Saupe order matrix.
428 @rtype: float
429 """
430
431
432 return Sxx - Syy
433
434
436 """Function for calculating the Axy value.
437
438 The equation for calculating the parameter is::
439
440 Sxy = 3/2 Axy.
441
442 @param Axy: The Axy component of the alignment tensor.
443 @type Axy: float
444 @rtype: float
445 """
446
447
448 return 3.0/2.0 * Axy
449
450
452 """Function for calculating the Axz value.
453
454 The equation for calculating the parameter is::
455
456 Sxz = 3/2 Axz.
457
458 @param Axz: The Axz component of the alignment tensor.
459 @type Axz: float
460 @rtype: float
461 """
462
463
464 return 3.0/2.0 * Axz
465
466
468 """Function for calculating the Ayy value.
469
470 The equation for calculating the parameter is::
471
472 Syy = 3/2 Ayy.
473
474 @param Ayy: The Ayy component of the alignment tensor.
475 @type Ayy: float
476 @rtype: float
477 """
478
479
480 return 3.0/2.0 * Ayy
481
482
484 """Function for calculating the Ayz value.
485
486 The equation for calculating the parameter is::
487
488 Syz = 3/2 Ayz.
489
490 @param Ayz: The Ayz component of the alignment tensor.
491 @type Ayz: float
492 @rtype: float
493 """
494
495
496 return 3.0/2.0 * Ayz
497
498
500 """Function for calculating the Szz value.
501
502 The equation for calculating the parameter is::
503
504 Szz = - Sxx - Syy.
505
506 @param Sxx: The Sxx component of the Saupe order matrix.
507 @type Sxx: float
508 @param Syy: The Syy component of the Saupe order matrix.
509 @type Syy: float
510 @return: The Szz component of the Saupe order matrix.
511 @rtype: float
512 """
513
514
515 return - Sxx - Syy
516
517
518 -def calc_P(Axx, Ayy, Azz, Axy, Axz, Ayz):
519 """Function for calculating the alignment tensor (in the structural frame).
520
521 @param Axx: The Axx tensor element.
522 @type Axx: float
523 @param Ayy: The Ayy tensor element.
524 @type Ayy: float
525 @param Azz: The Azz tensor element.
526 @type Azz: float
527 @param Axy: The Axy tensor element.
528 @type Axy: float
529 @param Axz: The Axz tensor element.
530 @type Axz: float
531 @param Ayz: The Ayz tensor element.
532 @type Ayz: float
533 @return: The alignment tensor (within the structural frame).
534 @rtype: 3x3 numpy float64 array
535 """
536
537
538 tensor = zeros((3, 3), float64)
539
540
541 tensor[0, 0] = Axx
542 tensor[1, 1] = Ayy
543 tensor[2, 2] = Azz
544
545
546 tensor[0, 1] = tensor[1, 0] = Axy
547 tensor[0, 2] = tensor[2, 0] = Axz
548 tensor[1, 2] = tensor[2, 1] = Ayz
549
550
551 tensor = tensor + eye(3)/3.0
552
553
554 return tensor
555
556
558 """Function for calculating the alignment tensor in the 5D vector notation.
559
560 @param Axx: The Axx tensor element.
561 @type Axx: float
562 @param Ayy: The Ayy tensor element.
563 @type Ayy: float
564 @param Azz: The Azz tensor element.
565 @type Azz: float
566 @param Axy: The Axy tensor element.
567 @type Axy: float
568 @param Axz: The Axz tensor element.
569 @type Axz: float
570 @param Ayz: The Ayz tensor element.
571 @type Ayz: float
572 @return: The alignment 5D tensor (within the structural frame).
573 @rtype: numpy rank-1 5D tensor
574 """
575
576
577 tensor = zeros(5, float64)
578
579
580 tensor[0] = Axx + 1.0/3.0
581 tensor[1] = Ayy + 1.0/3.0
582 tensor[2] = Axy
583 tensor[3] = Axz
584 tensor[4] = Ayz
585
586
587 return tensor
588
589
591 """Calculate the diagonalised alignment tensor.
592
593 The diagonalised alignment tensor is defined as::
594
595 | Pxx' 0 0 |
596 tensor = | 0 Pyy' 0 |.
597 | 0 0 Pzz'|
598
599 The diagonalised alignment tensor is calculated by eigenvalue decomposition.
600
601
602 @param tensor: The full alignment tensor in its eigenframe.
603 @type tensor: numpy array ((3, 3), float64)
604 @return: The diagonalised alignment tensor.
605 @rtype: numpy array ((3, 3), float64)
606 """
607
608
609 vals = eigvals(tensor)
610
611
612 abs_vals = abs(vals).tolist()
613 Pxx_index = abs_vals.index(min(abs_vals))
614 Pzz_index = abs_vals.index(max(abs_vals))
615 last_index = range(3)
616 last_index.pop(max(Pxx_index, Pzz_index))
617 last_index.pop(min(Pxx_index, Pzz_index))
618 Pyy_index = last_index[0]
619
620
621 tensor_diag = zeros((3, 3), float64)
622
623
624 tensor_diag[0, 0] = vals[Pxx_index]
625 tensor_diag[1, 1] = vals[Pyy_index]
626 tensor_diag[2, 2] = vals[Pzz_index]
627
628
629 tensor = tensor + eye(3)/3.0
630
631
632 return tensor_diag
633
634
636 """Function for calculating the Pxx value.
637
638 The equation for calculating the parameter is::
639
640 Pxx = Axx + 1/3.
641
642 @param Axx: The Axx component of the alignment tensor.
643 @type Axx: float
644 @rtype: float
645 """
646
647
648 return Axx + 1.0/3.0
649
650
652 """Function for calculating the Pxx-yy value.
653
654 The equation for calculating the parameter is::
655
656 Pxx-yy = Pxx - Pyy.
657
658 @param Pxx: The Pxx component of the alignment tensor.
659 @type Pxx: float
660 @param Pyy: The Pyy component of the alignment tensor.
661 @type Pyy: float
662 @return: The Pxx-yy component of the alignment tensor.
663 @rtype: float
664 """
665
666
667 return Pxx - Pyy
668
669
671 """Function for calculating the Pxy value.
672
673 The equation for calculating the parameter is::
674
675 Pxy = Axy.
676
677 @param Axy: The Axy component of the alignment tensor.
678 @type Axy: float
679 @rtype: float
680 """
681
682
683 return Axy
684
685
687 """Function for calculating the Pxz value.
688
689 The equation for calculating the parameter is::
690
691 Pxz = Axz.
692
693 @param Axz: The Axz component of the alignment tensor.
694 @type Axz: float
695 @rtype: float
696 """
697
698
699 return Axz
700
701
703 """Function for calculating the Pyy value.
704
705 The equation for calculating the parameter is::
706
707 Pyy = Ayy + 1/3.
708
709 @param Ayy: The Ayy component of the alignment tensor.
710 @type Ayy: float
711 @rtype: float
712 """
713
714
715 return Ayy + 1.0/3.0
716
717
719 """Function for calculating the Pyz value.
720
721 The equation for calculating the parameter is::
722
723 Pyz = Ayz.
724
725 @param Ayz: The Ayz component of the alignment tensor.
726 @type Ayz: float
727 @rtype: float
728 """
729
730
731 return Ayz
732
733
735 """Function for calculating the Pzz value.
736
737 The equation for calculating the parameter is::
738
739 Pzz = 1 - Pxx - Pyy.
740
741 @param Pxx: The Pxx component of the alignment tensor.
742 @type Pxx: float
743 @param Pyy: The Pyy component of the alignment tensor.
744 @type Pyy: float
745 @return: The Pzz component of the alignment tensor.
746 @rtype: float
747 """
748
749
750 return 1.0 - Pxx - Pyy
751
752
754 """Calculate the rhombicity parameter R.
755
756 This is given by::
757
758 R = Ar / Aa.
759
760
761 @param Aa: The Aa parameter.
762 @type Aa: float
763 @param Ar: The Ar parameter.
764 @type Ar: float
765 @return: The R parameter.
766 @rtype: float
767 """
768
769
770 if Aa == 0:
771 return nan
772
773
774 return Ar / Aa
775
776
778 """Calculate the rotation matrix from the molecular frame to the tensor frame.
779
780 This is defined by::
781
782 | Azz | >= | Ayy | >= | Axx |.
783
784
785 @param A: The full alignment tensor.
786 @type A: numpy array ((3, 3), float64)
787 @return: The array of x, y, and z indices.
788 @rtype: list
789 """
790
791
792 vals, rot = eig(A)
793
794
795 abs_vals = abs(vals).tolist()
796 x_index = abs_vals.index(min(abs_vals))
797 z_index = abs_vals.index(max(abs_vals))
798 last_index = range(3)
799 last_index.pop(max(x_index, z_index))
800 last_index.pop(min(x_index, z_index))
801 y_index = last_index[0]
802
803
804 rot_perm = zeros((3, 3), float64)
805
806
807 perm = [x_index, y_index, z_index]
808 for i in range(3):
809 for j in range(3):
810 rot_perm[i, j] = rot[i, perm[j]]
811
812
813 if abs(det(rot_perm) - 1.0) > 1e-7:
814 rot_perm[:, 0] = -rot_perm[:, 0]
815
816
817 return rot_perm
818
819
821 """Calculate the x unit vector.
822
823 This is given by the eigenvalue decomposition.
824
825
826 @param rotation: The rotation matrix.
827 @type rotation: numpy 3D, rank-2 array
828 @return: The x unit vector.
829 @rtype: numpy array (float64)
830 """
831
832
833 return rotation[:, 0]
834
835
837 """Calculate the y unit vector.
838
839 This is given by the eigenvalue decomposition.
840
841
842 @param rotation: The rotation matrix.
843 @type rotation: numpy 3D, rank-2 array
844 @return: The y unit vector.
845 @rtype: numpy array (float64)
846 """
847
848
849 return rotation[:, 1]
850
851
853 """Calculate the z unit vector.
854
855 This is given by the eigenvalue decomposition.
856
857
858 @param rotation: The rotation matrix.
859 @type rotation: numpy 3D, rank-2 array
860 @return: The z unit vector.
861 @rtype: numpy array (float64)
862 """
863
864
865 return rotation[:, 2]
866
867
869 """Generator for the automatic updating the alignment tensor data structures.
870
871 @return: This generator successively yields three objects, the target object to update, the list of parameters which if modified cause the target to be updated, and the list of parameters that the target depends upon.
872 """
873
874
875 yield ('A', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz'])
876 yield ('A_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz'])
877 yield ('Axxyy', ['Axx', 'Ayy'], ['Axx', 'Ayy'])
878 yield ('Azz', ['Axx', 'Ayy'], ['Axx', 'Ayy'])
879
880 yield ('P', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz'])
881 yield ('P_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz'])
882 yield ('Pxx', ['Axx'], ['Axx'])
883 yield ('Pxxyy', ['Axx', 'Ayy'], ['Axx', 'Ayy'])
884 yield ('Pxy', ['Axy'], ['Axy'])
885 yield ('Pxz', ['Axz'], ['Axz'])
886 yield ('Pyy', ['Ayy'], ['Ayy'])
887 yield ('Pyz', ['Ayz'], ['Ayz'])
888
889 yield ('Sxx', ['Axx'], ['Axx'])
890 yield ('Sxy', ['Axy'], ['Axy'])
891 yield ('Sxz', ['Axz'], ['Axz'])
892 yield ('Syy', ['Ayy'], ['Ayy'])
893 yield ('Syz', ['Ayz'], ['Ayz'])
894
895
896 yield ('A_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A'])
897 yield ('eigvals', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A'])
898 yield ('rotation', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A'])
899
900 yield ('P_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['P'])
901 yield ('Pzz', ['Axx', 'Ayy'], ['Pxx', 'Pyy'])
902
903 yield ('S', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Sxx', 'Syy', 'Szz', 'Sxy', 'Sxz', 'Syz'])
904 yield ('S_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Sxx', 'Syy', 'Szz', 'Sxy', 'Sxz', 'Syz'])
905 yield ('S_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['S'])
906 yield ('Sxxyy', ['Axx', 'Ayy'], ['Sxx', 'Syy'])
907 yield ('Szz', ['Axx', 'Ayy'], ['Sxx', 'Syy'])
908
909
910 yield ('Aa', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag'])
911 yield ('Ar', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag'])
912 yield ('eta', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag'])
913
914 yield ('unit_x', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation'])
915 yield ('unit_y', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation'])
916 yield ('unit_z', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation'])
917
918 yield ('euler', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation'])
919
920
921 yield ('R', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Aa', 'Ar'])
922
923
924
925
926
927
929 """List type data container for holding all the alignment tensors.
930
931 The elements of the list should be AlignTensorData instances.
932 """
933
935 """Replacement function for displaying an instance of this class."""
936
937 text = "Alignment tensors.\n\n"
938 text = text + "%-8s%-20s\n" % ("Index", "Name")
939 for i in xrange(len(self)):
940 text = text + "%-8i%-20s\n" % (i, self[i].name)
941 text = text + "\nThese can be accessed by typing 'pipe.align_tensor[index]'.\n"
942 return text
943
944
949
950
951 - def from_xml(self, align_tensor_super_node, file_version=1):
952 """Recreate the alignment tensor data structure from the XML alignment tensor node.
953
954 @param align_tensor_super_node: The alignment tensor XML nodes.
955 @type align_tensor_super_node: xml.dom.minicompat.Element instance
956 @keyword file_version: The relax XML version of the XML file.
957 @type file_version: int
958 """
959
960
961 xml_to_object(align_tensor_super_node, self, file_version=file_version, blacklist=['align_tensor'])
962
963
964 align_tensor_nodes = align_tensor_super_node.getElementsByTagName('align_tensor')
965
966
967 for align_tensor_node in align_tensor_nodes:
968
969 self.add_item(align_tensor_node.getAttribute('name'))
970
971
972 xml_to_object(align_tensor_node, self[-1], file_version=file_version)
973
974
976 """Return a list of the alignment tensor names."""
977
978
979 names = []
980 for i in xrange(len(self)):
981 names.append(self[i].name)
982
983
984 return names
985
986
987 - def to_xml(self, doc, element):
988 """Create an XML element for the alignment tensors.
989
990 @param doc: The XML document object.
991 @type doc: xml.dom.minidom.Document instance
992 @param element: The element to add the alignment tensors XML element to.
993 @type element: XML element object
994 """
995
996
997 tensor_list_element = doc.createElement('align_tensors')
998 element.appendChild(tensor_list_element)
999
1000
1001 tensor_list_element.setAttribute('desc', 'Alignment tensor list')
1002
1003
1004 fill_object_contents(doc, tensor_list_element, object=self, blacklist=list(self.__class__.__dict__.keys() + list.__dict__.keys()))
1005
1006
1007 for i in xrange(len(self)):
1008
1009 tensor_element = doc.createElement('align_tensor')
1010 tensor_list_element.appendChild(tensor_element)
1011 tensor_element.setAttribute('index', repr(i))
1012 tensor_element.setAttribute('desc', 'Alignment tensor')
1013
1014
1015 fill_object_contents(doc, tensor_element, object=self[i], blacklist=list(self[i].__class__.__dict__.keys()))
1016
1017
1019 """An empty data container for the alignment tensor elements."""
1020
1021
1022 __mod_attr__ = ['name',
1023 'Axx', 'Axx_sim', 'Axx_err',
1024 'Ayy', 'Ayy_sim', 'Ayy_err',
1025 'Axy', 'Axy_sim', 'Axy_err',
1026 'Axz', 'Axz_sim', 'Axz_err',
1027 'Ayz', 'Ayz_sim', 'Ayz_err',
1028 'domain',
1029 'red',
1030 'fixed']
1031
1032 - def __init__(self, name, fixed=False):
1033 """Set up the tensor data.
1034
1035 @param name: The tensor ID string.
1036 @type name: str
1037 @keyword fixed: The optimisation flag.
1038 @type fixed: bool
1039 """
1040
1041
1042 self.name = name
1043 self.fixed = fixed
1044
1045
1047 """Function for calculating the parameters, unit vectors, and tensors on the fly.
1048
1049 @param name: The name of the object to set.
1050 @type name: str
1051 @param value: The value to set the object corresponding to the name argument to.
1052 @type value: Any Python object type
1053 """
1054
1055
1056 if search('_err$', name):
1057 category = 'err'
1058 param_name = name[:-4]
1059 elif search('_sim$', name):
1060 category = 'sim'
1061 param_name = name[:-4]
1062 else:
1063 category = 'val'
1064 param_name = name
1065
1066
1067 if not param_name in self.__mod_attr__:
1068 raise RelaxError("The object " + repr(name) + " is not modifiable.")
1069
1070
1071 self.__dict__[name] = value
1072
1073
1074 for target, update_if_set, depends in dependency_generator():
1075 self.__update_object(param_name, target, update_if_set, depends, category)
1076
1077
1079 """Update the Monte Carlo simulation data lists when a simulation value is appended.
1080
1081 @param param_name: The MC sim parameter name which is being appended to.
1082 @type param_name: str
1083 @param index: The index of the Monte Carlo simulation which was set.
1084 @type index: int
1085 """
1086
1087
1088 for target, update_if_set, depends in dependency_generator():
1089
1090 if not param_name in update_if_set:
1091 continue
1092
1093
1094 fn = globals()['calc_'+target]
1095
1096
1097 missing_dep = 0
1098 deps = ()
1099 for dep_name in depends:
1100
1101 if dep_name != 'type':
1102 dep_name = dep_name+'_sim'
1103
1104
1105 if not hasattr(self, dep_name):
1106 missing_dep = 1
1107 break
1108
1109
1110 dep_obj = getattr(self, dep_name)
1111
1112
1113 if dep_name == 'type':
1114 deps = deps+(dep_obj,)
1115 continue
1116
1117
1118 if len(dep_obj) <= index:
1119 missing_dep = 1
1120 break
1121
1122
1123 deps = deps+(dep_obj[index],)
1124
1125
1126 if not missing_dep:
1127
1128 target_obj = getattr(self, target+'_sim')
1129
1130
1131 target_obj.append_untouchable_item(fn(*deps))
1132
1133
1135 """Update the Monte Carlo simulation data lists when a simulation value is set.
1136
1137 @param param_name: The MC sim parameter name which is being set.
1138 @type param_name: str
1139 @param index: The index of the Monte Carlo simulation which was set.
1140 @type index: int
1141 """
1142
1143
1144 for target, update_if_set, depends in dependency_generator():
1145
1146 if not param_name in update_if_set:
1147 continue
1148
1149
1150 fn = globals()['calc_'+target]
1151
1152
1153 missing_dep = 0
1154 deps = ()
1155 for dep_name in depends:
1156
1157 if dep_name != 'type':
1158 dep_name = dep_name+'_sim'
1159
1160
1161 if not hasattr(self, dep_name):
1162 missing_dep = 1
1163 break
1164
1165
1166 dep_obj = getattr(self, dep_name)
1167
1168
1169 if dep_name == 'type':
1170 deps = deps+(dep_obj,)
1171 continue
1172
1173
1174 if len(dep_obj) <= index:
1175 missing_dep = 1
1176 break
1177
1178
1179 deps = deps+(dep_obj[index],)
1180
1181
1182 if not missing_dep:
1183
1184 target_obj = getattr(self, target+'_sim')
1185
1186
1187 target_obj.set_untouchable_item(index, fn(*deps))
1188
1189
1190 - def __update_object(self, param_name, target, update_if_set, depends, category):
1191 """Function for updating the target object, its error, and the MC simulations.
1192
1193 If the base name of the object is not within the 'update_if_set' list, this function returns
1194 without doing anything (to avoid wasting time). Dependant upon the category the object
1195 (target), its error (target+'_err'), or all Monte Carlo simulations (target+'_sim') are
1196 updated.
1197
1198 @param param_name: The parameter name which is being set in the __setattr__() function.
1199 @type param_name: str
1200 @param target: The name of the object to update.
1201 @type target: str
1202 @param update_if_set: If the parameter being set by the __setattr__() function is not
1203 within this list of parameters, don't waste time updating the
1204 target.
1205 @param depends: An array of names objects that the target is dependent upon.
1206 @type depends: array of str
1207 @param category: The category of the object to update (one of 'val', 'err', or
1208 'sim').
1209 @type category: str
1210 @return: None
1211 """
1212
1213
1214 if not param_name in update_if_set:
1215 return
1216
1217
1218 fn = globals()['calc_'+target]
1219
1220
1221
1222
1223
1224 if category == 'val':
1225
1226 missing_dep = 0
1227 deps = ()
1228 for dep_name in depends:
1229
1230 if not hasattr(self, dep_name):
1231 missing_dep = 1
1232 break
1233
1234
1235 deps = deps+(getattr(self, dep_name),)
1236
1237
1238 if not missing_dep:
1239
1240 value = fn(*deps)
1241
1242
1243 self.__dict__[target] = value
1244
1245
1246
1247
1248
1249 if category == 'err':
1250
1251 missing_dep = 0
1252 deps = ()
1253 for dep_name in depends:
1254
1255 if not hasattr(self, dep_name+'_err'):
1256 missing_dep = 1
1257 break
1258
1259
1260 deps = deps+(getattr(self, dep_name+'_err'),)
1261
1262
1263 if not missing_dep:
1264
1265 value = fn(*deps)
1266
1267
1268 self.__dict__[target+'_err'] = value
1269
1270
1271
1272
1273
1274 if category == 'sim':
1275
1276 missing_dep = 0
1277 deps = []
1278 for dep_name in depends:
1279
1280 if dep_name != 'type':
1281 dep_name = dep_name+'_sim'
1282
1283
1284 if not hasattr(self, dep_name):
1285 missing_dep = 1
1286 break
1287
1288
1289 if not missing_dep:
1290
1291 if not target+'_sim' in self.__dict__:
1292 self.__dict__[target+'_sim'] = AlignTensorSimList(target, self)
1293
1294
1295
1297 """Empty data container for Monte Carlo simulation alignment tensor data."""
1298
1299 - def __init__(self, param_name, align_element):
1300 """Initialise the Monte Carlo simulation parameter list.
1301
1302 This function makes the parameter name and parent object accessible to the functions of this
1303 list object.
1304 """
1305
1306 self.param_name = param_name
1307 self.align_element = align_element
1308
1309
1311 """Set the value."""
1312
1313
1314 ListType.__setitem__(self, index, value)
1315
1316
1317 self.align_element._AlignTensorData__update_sim_set(self.param_name, index)
1318
1319
1321 """Replacement function for the normal self.append() method."""
1322
1323
1324 self[len(self):len(self)] = [value]
1325
1326
1327 self.align_element._AlignTensorData__update_sim_append(self.param_name, len(self)-1)
1328
1329
1331 """Append the value for an untouchable MC data structure."""
1332
1333
1334 self[len(self):len(self)] = [value]
1335
1336
1338 """Set the value for an untouchable MC data structure."""
1339
1340
1341 ListType.__setitem__(self, index, value)
1342